def send_request(self, job_request, message_expiry_in_seconds=None):
        """
        Send a JobRequest, and return a request ID.

        The context and control_extra arguments may be used to include extra values in the
        context and control headers, respectively.

        :param job_request: The job request object to send
        :type job_request: JobRequest
        :param message_expiry_in_seconds: How soon the message will expire if not received by a server (defaults to
                                          sixty seconds unless the settings are otherwise)
        :type message_expiry_in_seconds: int

        :return: The request ID
        :rtype: int

        :raise: ConnectionError, InvalidField, MessageSendError, MessageSendTimeout, MessageTooLarge
        """
        request_id = self.request_counter
        self.request_counter += 1
        meta = {}
        wrapper = self._make_middleware_stack(
            [m.request for m in self.middleware],
            self._base_send_request,
        )
        try:
            with self.metrics.timer('client.send.including_middleware', resolution=TimerResolution.MICROSECONDS):
                wrapper(request_id, meta, job_request, message_expiry_in_seconds)
            return request_id
        finally:
            self.metrics.commit()