class_docstr: Stores an API request's inputs, outputs, and other metadata. Contains a method to make an API
  call.
docstr: Calls the OpenAI API and stores results.
docstr_tok: ["Calls","the","OpenAI","API","and","stores","results","."]
code: def call_api(
      self, retry_queue: queue.Queue, status_tracker: StatusTracker
  ):
      """Calls the OpenAI API and stores results."""
      _logger.debug(f"Request #{self.index} started")
      try:
          api_key = os.environ["OPENAI_API_KEY"]
          request_header = {"Authorization": f"Bearer {api_key}"}
          # use api-key header for Azure deployments
          if "/deployments" in self.request_url:
              request_header = {"api-key": f"{api_key}"}
          response = requests.post(
              url=self.request_url,
              headers=request_header,
              json=self.request_json,
              timeout=self.timeout,
          )
          response_json = response.json()
  
          # Refer to error codes: https://platform.openai.com/docs/guides/error-codes/api-errors
          if "error" in response_json:
              error = response_json["error"]
              logging.warning(
                  f"Request #{self.index} failed with error {error}"
              )
              status_tracker.num_api_errors += 1
              # Rate limit error
              if "Rate limit" in error.get("message", ""):
                  _logger.debug(
                      f"Request #{self.index} failed with {error!r}"
                  )
                  current_time = time.time()
                  status_tracker.time_of_last_rate_limit_error = (
                      current_time
                  )
                  status_tracker.increment_num_rate_limit_errors()
                  # check time since first request, fail at 10 minutes
                  if current_time - self.start_time < 600:
                      if current_time - self.last_log_time > 60:
                          _logger.warning(
                              "Retrying for request failed with rate limit."
                          )
                          self.last_log_time = current_time
                      retry_queue.put_nowait(self)
                  else:
                      _logger.warning(
                          "Request failed after retrying for 10 minutes."
                      )
                      status_tracker.complete_task(success=False)
                      status_tracker.error = mlflow.MlflowException(
                          "Request failed after retrying for 10 minutes."
                      )
              # Other retryable errors
              elif response.status_code in [500, 503]:
                  _logger.debug(
                      f"Request #{self.index} failed with {error!r}"
                  )
                  status_tracker.increment_num_api_errors()
                  if self.attempts_left > 0:
                      retry_queue.put_nowait(self)
                  else:
                      status_tracker.complete_task(success=False)
                      status_tracker.error = mlflow.MlflowException(
                          f"Request #{self.index} failed with {error!r}"
                      )
              # Unretryable errors
              else:
                  _logger.warning(
                      f"Request #{self.index} failed with {error!r}"
                  )
                  status_tracker.increment_num_api_errors()
                  status_tracker.complete_task(success=False)
                  if response.status_code == 401:
                      status_tracker.error = mlflow.MlflowException(
                          f"Authentication Error for OpenAI. Error response:\n {error!r}",
                          error_code=UNAUTHENTICATED,
                      )
                  else:
                      status_tracker.error = mlflow.MlflowException(
                          f"Request #{self.index} to OpenAI failed. Error response: {error}"
                      )
          else:
              _logger.debug(f"Request #{self.index} succeeded")
              status_tracker.complete_task(success=True)
              self.results.append((self.index, response_json))
      except Exception as e:
          _logger.debug(f"Request #{self.index} failed with {e!r}")
          status_tracker.increment_num_api_errors()
          status_tracker.complete_task(success=False)
          status_tracker.error = e
  
imports: from __future__ import annotations
  import logging
  import os
  import queue
  import threading
  import time
  from concurrent.futures import ThreadPoolExecutor
  from dataclasses import dataclass
  import requests
  import tiktoken
  import mlflow
  from mlflow.protos.databricks_pb2 import UNAUTHENTICATED
  from mlflow.utils.openai_utils import _OAITokenHolder
label_desc: Use image node_id 1 for calling the APIRequest obj's underlying member method code with example usage: obj.call_api(retry_queue, status_tracker) without return types