docs: def call_jobs_parallel_future(
          self,
          jobs,
          expansions=None,
          raise_job_errors=True,
          raise_action_errors=True,
          catch_transport_errors=False,
          timeout=None,
          **kwargs
      ):
          """
          This method is identical in signature and behavior to `call_jobs_parallel`, except that it sends the requests
          and then immediately returns a `FutureResponse` instead of blocking waiting on all responses and returning
          a `list` of `JobResponses`. Just call `result(timeout=None)` on the future response to block for an available
          response. Some of the possible exceptions may be raised when this method is called; others may be raised when
          the future is used.
  
          :return: A future from which the list of job responses can later be retrieved
          :rtype: Client.FutureResponse
          """
          kwargs.pop('suppress_response', None)  # If this kwarg is used, this method would always result in a timeout
          if timeout:
              kwargs['message_expiry_in_seconds'] = timeout
  
          error_key = 0
          transport_errors = {}
  
          response_reassembly_keys = []
          service_request_ids = {}
          for job in jobs:
              try:
                  sent_request_id = self.send_request(job['service_name'], job['actions'], **kwargs)
                  service_request_ids.setdefault(job['service_name'], set()).add(sent_request_id)
              except (ConnectionError, InvalidMessageError, MessageSendError, MessageSendTimeout, MessageTooLarge) as e:
                  if not catch_transport_errors:
                      raise
                  sent_request_id = error_key = error_key - 1
                  transport_errors[(job['service_name'], sent_request_id)] = e
  
              response_reassembly_keys.append((job['service_name'], sent_request_id))
  
          def get_response(_timeout):
              service_responses = {}
              for service_name, request_ids in six.iteritems(service_request_ids):
                  try:
                      for request_id, response in self.get_all_responses(
                          service_name,
                          receive_timeout_in_seconds=_timeout or timeout,
                      ):
                          if request_id not in request_ids:
                              raise Exception(
                                  'Got response ID {}, not in set of expected IDs {}'.format(request_id, request_ids)
                              )
                          service_responses[(service_name, request_id)] = response
                          if catch_transport_errors:
                              # We don't need the set to be reduced unless we're catching errors
                              request_ids.remove(request_id)
                  except (ConnectionError, InvalidMessageError, MessageReceiveError, MessageReceiveTimeout) as e:
                      if not catch_transport_errors:
                          raise
                      for request_id in request_ids:
                          transport_errors[(service_name, request_id)] = e
  
              responses = []
              actions_to_expand = []
              for service_name, request_id in response_reassembly_keys:
                  if request_id < 0:
                      # A transport error occurred during send, and we are catching errors, so add it to the list
                      responses.append(transport_errors[(service_name, request_id)])
                      continue
  
                  if (service_name, request_id) not in service_responses:
                      if (service_name, request_id) in transport_errors:
                          # A transport error occurred during receive, and we are catching errors, so add it to the list
                          responses.append(transport_errors[(service_name, request_id)])
                          continue
  
                      # It shouldn't be possible for this to happen unless the code has a bug, but let's raise a
                      # meaningful exception just in case a bug exists, because KeyError will not be helpful.
                      raise Exception('There was no response for service {}, request {}'.format(service_name, request_id))
  
                  response = service_responses[(service_name, request_id)]
                  if raise_job_errors and response.errors:
                      raise self.JobError(response.errors)
                  if raise_action_errors:
                      error_actions = [action for action in response.actions if action.errors]
                      if error_actions:
                          raise self.CallActionError(error_actions)
                  if expansions:
                      actions_to_expand.extend(response.actions)
  
                  responses.append(response)
  
              if expansions:
                  kwargs.pop('continue_on_error', None)
                  self._perform_expansion(actions_to_expand, expansions, **kwargs)
  
              return responses
  
          return self.FutureResponse(get_response)