def close(self, exception=None):
        """
        Close down the handler. If the handler has already closed,
        this will be a no op. An optional exception can be passed in to
        indicate that the handler was shutdown due to error.

        :param exception: An optional exception if the handler is closing
         due to an error.
        :type exception: Exception

        Example:
            .. literalinclude:: ../examples/test_examples_eventhub.py
                :start-after: [START eventhub_client_receiver_close]
                :end-before: [END eventhub_client_receiver_close]
                :language: python
                :dedent: 4
                :caption: Close down the handler.

        """
        self.running = False
        if self.error:
            return
        if isinstance(exception, errors.LinkRedirect):
            self.redirected = exception
        elif isinstance(exception, EventHubError):
            self.error = exception
        elif exception:
            self.error = EventHubError(str(exception))
        else:
            self.error = EventHubError("This receive handler is now closed.")
        self._handler.close()
    def receive(self, max_batch_size=None, timeout=None):
        """
        Receive events from the EventHub.

        :param max_batch_size: Receive a batch of events. Batch size will
         be up to the maximum specified, but will return as soon as service
         returns no new events. If combined with a timeout and no events are
         retrieve before the time, the result will be empty. If no batch
         size is supplied, the prefetch size will be the maximum.
        :type max_batch_size: int
        :rtype: list[~azure.eventhub.common.EventData]
        """
        if self.error:
            raise self.error
        try:
            timeout_ms = 1000 * timeout if timeout else 0
            message_batch = self._handler.receive_message_batch(
                max_batch_size=max_batch_size, timeout=timeout_ms)
            data_batch = []
            for message in message_batch:
                event_data = EventData(message=message)
                self.offset = event_data.offset
                data_batch.append(event_data)
            return data_batch
        except errors.LinkDetach as detach:
            error = EventHubError(str(detach))
            self.close(exception=error)
            raise error
        except Exception as e:
            error = EventHubError("Receive failed: {}".format(e))
            self.close(exception=error)
            raise error
Beispiel #3
0
 def wait(self):
     """
     Wait until all transferred events have been sent.
     """
     if self.error:
         raise self.error
     if not self.running:
         raise ValueError("Unable to send until client has been started.")
     try:
         self._handler.wait()
     except (errors.LinkDetach, errors.ConnectionClose) as shutdown:
         if shutdown.action.retry and self.auto_reconnect:
             self.reconnect()
         else:
             error = EventHubError(str(shutdown), shutdown)
             self.close(exception=error)
             raise error
     except errors.MessageHandlerError as shutdown:
         if self.auto_reconnect:
             self.reconnect()
         else:
             error = EventHubError(str(shutdown), shutdown)
             self.close(exception=error)
             raise error
     except Exception as e:
         raise EventHubError("Send failed: {}".format(e))
    def send(self, event_data):
        """
        Sends an event data and blocks until acknowledgement is
        received or operation times out.

        :param event_data: The event to be sent.
        :type event_data: ~azure.eventhub.common.EventData
        :raises: ~azure.eventhub.common.EventHubError if the message fails to
         send.
        :return: The outcome of the message send.
        :rtype: ~uamqp.constants.MessageSendResult
        """
        if self.error:
            raise self.error
        if event_data.partition_key and self.partition:
            raise ValueError(
                "EventData partition key cannot be used with a partition sender."
            )
        event_data.message.on_send_complete = self._on_outcome
        try:
            self._handler.send_message(event_data.message)
            if self._outcome != constants.MessageSendResult.Ok:
                raise Sender._error(self._outcome, self._condition)
        except errors.LinkDetach as detach:
            error = EventHubError(str(detach))
            self.close(exception=error)
            raise error
        except Exception as e:
            error = EventHubError("Send failed: {}".format(e))
            self.close(exception=error)
            raise error
        else:
            return self._outcome
 def _reconnect(self):  # pylint: disable=too-many-statements
     # pylint: disable=protected-access
     alt_creds = {
         "username": self.client._auth_config.get("iot_username"),
         "password": self.client._auth_config.get("iot_password")}
     self._handler.close()
     source = Source(self.source)
     if self.offset is not None:
         source.set_filter(self.offset.selector())
     self._handler = ReceiveClient(
         source,
         auth=self.client.get_auth(**alt_creds),
         debug=self.client.debug,
         prefetch=self.prefetch,
         link_properties=self.properties,
         timeout=self.timeout,
         error_policy=self.retry_policy,
         keep_alive_interval=self.keep_alive,
         client_name=self.name,
         properties=self.client.create_properties())
     try:
         self._handler.open()
         while not self._handler.client_ready():
             time.sleep(0.05)
         return True
     except errors.TokenExpired as shutdown:
         log.info("Receiver disconnected due to token expiry. Shutting down.")
         error = EventHubError(str(shutdown), shutdown)
         self.close(exception=error)
         raise error
     except (errors.LinkDetach, errors.ConnectionClose) as shutdown:
         if shutdown.action.retry and self.auto_reconnect:
             log.info("Receiver detached. Attempting reconnect.")
             return False
         log.info("Receiver detached. Shutting down.")
         error = EventHubError(str(shutdown), shutdown)
         self.close(exception=error)
         raise error
     except errors.MessageHandlerError as shutdown:
         if self.auto_reconnect:
             log.info("Receiver detached. Attempting reconnect.")
             return False
         log.info("Receiver detached. Shutting down.")
         error = EventHubError(str(shutdown), shutdown)
         self.close(exception=error)
         raise error
     except errors.AMQPConnectionError as shutdown:
         if str(shutdown).startswith("Unable to open authentication session") and self.auto_reconnect:
             log.info("Receiver couldn't authenticate. Attempting reconnect.")
             return False
         log.info("Receiver connection error (%r). Shutting down.", shutdown)
         error = EventHubError(str(shutdown))
         self.close(exception=error)
         raise error
     except Exception as e:
         log.info("Unexpected error occurred (%r). Shutting down.", e)
         error = EventHubError("Receiver reconnect failed: {}".format(e))
         self.close(exception=error)
         raise error
    def send(self, event_data):
        """
        Sends an event data and blocks until acknowledgement is
        received or operation times out.

        :param event_data: The event to be sent.
        :type event_data: ~azure.eventhub.common.EventData
        :raises: ~azure.eventhub.common.EventHubError if the message fails to
         send.
        :return: The outcome of the message send.
        :rtype: ~uamqp.constants.MessageSendResult
        """
        if self.error:
            raise self.error
        if not self.running:
            raise ValueError("Unable to send until client has been started.")
        if event_data.partition_key and self.partition:
            raise ValueError(
                "EventData partition key cannot be used with a partition sender."
            )
        event_data.message.on_send_complete = self._on_outcome
        try:
            self._handler.send_message(event_data.message)
            if self._outcome != constants.MessageSendResult.Ok:
                raise Sender._error(self._outcome, self._condition)
        except errors.MessageException as failed:
            error = EventHubError(str(failed), failed)
            self.close(exception=error)
            raise error
        except (errors.TokenExpired, errors.AuthenticationException):
            log.info(
                "Sender disconnected due to token error. Attempting reconnect."
            )
            self.reconnect()
        except (errors.LinkDetach, errors.ConnectionClose) as shutdown:
            if shutdown.action.retry and self.auto_reconnect:
                log.info("Sender detached. Attempting reconnect.")
                self.reconnect()
            else:
                log.info("Sender detached. Shutting down.")
                error = EventHubError(str(shutdown), shutdown)
                self.close(exception=error)
                raise error
        except errors.MessageHandlerError as shutdown:
            if self.auto_reconnect:
                log.info("Sender detached. Attempting reconnect.")
                self.reconnect()
            else:
                log.info("Sender detached. Shutting down.")
                error = EventHubError(str(shutdown), shutdown)
                self.close(exception=error)
                raise error
        except Exception as e:
            log.info("Unexpected error occurred (%r). Shutting down.", e)
            error = EventHubError("Send failed: {}".format(e))
            self.close(exception=error)
            raise error
        else:
            return self._outcome
Beispiel #7
0
 def _handle_redirect(self, redirects):
     if len(redirects) != len(self.clients):
         raise EventHubError("Some clients are attempting to redirect the connection.")
     if not all(r.hostname == redirects[0].hostname for r in redirects):
         raise EventHubError("Multiple clients attempting to redirect to different hosts.")
     self._process_redirect_uri(redirects[0])
     for client in self.clients:
         client.open()
    def receive(self, max_batch_size=None, timeout=None):
        """
        Receive events from the EventHub.

        :param max_batch_size: Receive a batch of events. Batch size will
         be up to the maximum specified, but will return as soon as service
         returns no new events. If combined with a timeout and no events are
         retrieve before the time, the result will be empty. If no batch
         size is supplied, the prefetch size will be the maximum.
        :type max_batch_size: int
        :rtype: list[~azure.eventhub.common.EventData]
        """
        if self.error:
            raise self.error
        if not self.running:
            raise ValueError("Unable to receive until client has been started.")
        data_batch = []
        try:
            timeout_ms = 1000 * timeout if timeout else 0
            message_batch = self._handler.receive_message_batch(
                max_batch_size=max_batch_size,
                timeout=timeout_ms)
            for message in message_batch:
                event_data = EventData(message=message)
                self.offset = event_data.offset
                data_batch.append(event_data)
            return data_batch
        except (errors.TokenExpired, errors.AuthenticationException):
            log.info("Receiver disconnected due to token error. Attempting reconnect.")
            self.reconnect()
            return data_batch
        except (errors.LinkDetach, errors.ConnectionClose) as shutdown:
            if shutdown.action.retry and self.auto_reconnect:
                log.info("Receiver detached. Attempting reconnect.")
                self.reconnect()
                return data_batch
            log.info("Receiver detached. Shutting down.")
            error = EventHubError(str(shutdown), shutdown)
            self.close(exception=error)
            raise error
        except errors.MessageHandlerError as shutdown:
            if self.auto_reconnect:
                log.info("Receiver detached. Attempting reconnect.")
                self.reconnect()
                return data_batch
            log.info("Receiver detached. Shutting down.")
            error = EventHubError(str(shutdown), shutdown)
            self.close(exception=error)
            raise error
        except Exception as e:
            log.info("Unexpected error occurred (%r). Shutting down.", e)
            error = EventHubError("Receive failed: {}".format(e))
            self.close(exception=error)
            raise error
 def _handle_redirect(self, redirects):
     if len(redirects) != len(self.clients):
         raise EventHubError(
             "Some clients are attempting to redirect the connection.")
     if not all(r.hostname == redirects[0].hostname for r in redirects):
         raise EventHubError(
             "Multiple clients attempting to redirect to different hosts.")
     self.auth = self._create_auth(redirects[0].address.decode('utf-8'),
                                   **self._auth_config)
     self.connection.redirect(redirects[0], self.auth)
     for client in self.clients:
         client.open(self.connection)
 def _reconnect(self):
     # pylint: disable=protected-access
     self._handler.close()
     unsent_events = self._handler.pending_messages
     self._handler = SendClient(self.target,
                                auth=self.client.get_auth(),
                                debug=self.client.debug,
                                msg_timeout=self.timeout,
                                error_policy=self.retry_policy,
                                keep_alive_interval=self.keep_alive,
                                client_name=self.name,
                                properties=self.client.create_properties())
     try:
         self._handler.open()
         self._handler.queue_message(*unsent_events)
         self._handler.wait()
         return True
     except errors.TokenExpired as shutdown:
         log.info("Sender disconnected due to token expiry. Shutting down.")
         error = EventHubError(str(shutdown), shutdown)
         self.close(exception=error)
         raise error
     except (errors.LinkDetach, errors.ConnectionClose) as shutdown:
         if shutdown.action.retry and self.auto_reconnect:
             log.info("Sender detached. Attempting reconnect.")
             return False
         log.info("Sender reconnect failed. Shutting down.")
         error = EventHubError(str(shutdown), shutdown)
         self.close(exception=error)
         raise error
     except errors.MessageHandlerError as shutdown:
         if self.auto_reconnect:
             log.info("Sender detached. Attempting reconnect.")
             return False
         log.info("Sender reconnect failed. Shutting down.")
         error = EventHubError(str(shutdown), shutdown)
         self.close(exception=error)
         raise error
     except errors.AMQPConnectionError as shutdown:
         if str(shutdown).startswith("Unable to open authentication session"
                                     ) and self.auto_reconnect:
             log.info("Sender couldn't authenticate. Attempting reconnect.")
             return False
         log.info("Sender connection error (%r). Shutting down.", shutdown)
         error = EventHubError(str(shutdown))
         self.close(exception=error)
         raise error
     except Exception as e:
         log.info("Unexpected error occurred (%r). Shutting down.", e)
         error = EventHubError("Sender Reconnect failed: {}".format(e))
         self.close(exception=error)
         raise error
Beispiel #11
0
    def run(self):
        """
        Run the EventHubClient in blocking mode.
        Opens the connection and starts running all Sender/Receiver clients.
        Returns a list of the start up results. For a succcesful client start the
        result will be `None`, otherwise the exception raised.
        If all clients failed to start, then run will fail, shut down the connection
        and raise an exception.
        If at least one client starts up successfully the run command will succeed.

        :rtype: list[~azure.eventhub.common.EventHubError]
        """
        log.info("%r: Starting %r clients", self.container_id, len(self.clients))
        try:
            self._start_clients()
            redirects = [c.redirected for c in self.clients if c.redirected]
            failed = [c.error for c in self.clients if c.error]
            if failed and len(failed) == len(self.clients):
                log.warning("%r: All clients failed to start.", self.container_id)
                raise failed[0]
            if failed:
                log.warning("%r: %r clients failed to start.", self.container_id, len(failed))
            elif redirects:
                self._handle_redirect(redirects)
        except EventHubError:
            self.stop()
            raise
        except Exception as e:
            self.stop()
            raise EventHubError(str(e))
        return failed
Beispiel #12
0
 def reconnect(self):
     """If the Receiver was disconnected from the service with
     a retryable error - attempt to reconnect."""
     # pylint: disable=protected-access
     alt_creds = {
         "username": self.client._auth_config.get("iot_username"),
         "password": self.client._auth_config.get("iot_password")
     }
     self._handler.close()
     source = Source(self.source)
     if self.offset is not None:
         source.set_filter(self.offset.selector())
     self._handler = ReceiveClient(
         source,
         auth=self.client.get_auth(**alt_creds),
         debug=self.client.debug,
         prefetch=self.prefetch,
         link_properties=self.properties,
         timeout=self.timeout,
         error_policy=self.retry_policy,
         keep_alive_interval=self.keep_alive,
         client_name=self.name,
         properties=self.client.create_properties())
     try:
         self._handler.open()
         while not self.has_started():
             self._handler._connection.work()
     except (errors.LinkDetach, errors.ConnectionClose) as shutdown:
         if shutdown.action.retry and self.auto_reconnect:
             self.reconnect()
         else:
             error = EventHubError(str(shutdown), shutdown)
             self.close(exception=error)
             raise error
     except errors.MessageHandlerError as shutdown:
         if self.auto_reconnect:
             self.reconnect()
         else:
             error = EventHubError(str(shutdown), shutdown)
             self.close(exception=error)
             raise error
     except Exception as e:
         error = EventHubError("Receiver reconnect failed: {}".format(e))
         self.close(exception=error)
         raise error
Beispiel #13
0
    def wait(self):
        """
        Wait until all transferred events have been sent.

        Example:
            .. literalinclude:: ../examples/test_examples_eventhub.py
                :start-after: [START eventhub_client_transfer]
                :end-before: [END eventhub_client_transfer]
                :language: python
                :dedent: 4
                :caption: Wait until all transferred events have been sent.

        """
        if self.error:
            raise self.error
        if not self.running:
            raise ValueError("Unable to send until client has been started.")
        try:
            self._handler.wait()
        except (errors.TokenExpired, errors.AuthenticationException):
            log.info("Sender disconnected due to token error. Attempting reconnect.")
            self.reconnect()
        except (errors.LinkDetach, errors.ConnectionClose) as shutdown:
            if shutdown.action.retry and self.auto_reconnect:
                log.info("Sender detached. Attempting reconnect.")
                self.reconnect()
            else:
                log.info("Sender detached. Shutting down.")
                error = EventHubError(str(shutdown), shutdown)
                self.close(exception=error)
                raise error
        except errors.MessageHandlerError as shutdown:
            if self.auto_reconnect:
                log.info("Sender detached. Attempting reconnect.")
                self.reconnect()
            else:
                log.info("Sender detached. Shutting down.")
                error = EventHubError(str(shutdown), shutdown)
                self.close(exception=error)
                raise error
        except Exception as e:
            log.info("Unexpected error occurred (%r).", e)
            raise EventHubError("Send failed: {}".format(e))
 def wait(self):
     """
     Wait until all transferred events have been sent.
     """
     if self.error:
         raise self.error
     try:
         self._handler.wait()
     except Exception as e:
         raise EventHubError("Send failed: {}".format(e))
    def close(self, exception=None):
        """
        Close down the handler. If the handler has already closed,
        this will be a no op. An optional exception can be passed in to
        indicate that the handler was shutdown due to error.

        :param exception: An optional exception if the handler is closing
         due to an error.
        :type exception: Exception
        """
        if self.error:
            return
        elif isinstance(exception, errors.LinkRedirect):
            self.redirected = exception
        elif isinstance(exception, EventHubError):
            self.error = exception
        elif exception:
            self.error = EventHubError(str(exception))
        else:
            self.error = EventHubError("This receive handler is now closed.")
        self._handler.close()
Beispiel #16
0
 def reconnect(self):
     """If the Sender was disconnected from the service with
     a retryable error - attempt to reconnect."""
     # pylint: disable=protected-access
     self._handler.close()
     unsent_events = self._handler.pending_messages
     self._handler = SendClient(self.target,
                                auth=self.client.get_auth(),
                                debug=self.client.debug,
                                msg_timeout=self.timeout,
                                error_policy=self.retry_policy,
                                keep_alive_interval=self.keep_alive,
                                client_name=self.name,
                                properties=self.client.create_properties())
     try:
         self._handler.open()
         self._handler.queue_message(*unsent_events)
         self._handler.wait()
     except (errors.LinkDetach, errors.ConnectionClose) as shutdown:
         if shutdown.action.retry and self.auto_reconnect:
             self.reconnect()
         else:
             error = EventHubError(str(shutdown), shutdown)
             self.close(exception=error)
             raise error
     except errors.MessageHandlerError as shutdown:
         if self.auto_reconnect:
             self.reconnect()
         else:
             error = EventHubError(str(shutdown), shutdown)
             self.close(exception=error)
             raise error
     except Exception as e:
         error = EventHubError("Sender Reconnect failed: {}".format(e))
         self.close(exception=error)
         raise error
 def wait(self):
     """
     Wait until all transferred events have been sent.
     """
     if self.error:
         raise self.error
     if not self.running:
         raise ValueError("Unable to send until client has been started.")
     try:
         self._handler.wait()
     except (errors.TokenExpired, errors.AuthenticationException):
         log.info(
             "Sender disconnected due to token error. Attempting reconnect."
         )
         self.reconnect()
     except (errors.LinkDetach, errors.ConnectionClose) as shutdown:
         if shutdown.action.retry and self.auto_reconnect:
             log.info("Sender detached. Attempting reconnect.")
             self.reconnect()
         else:
             log.info("Sender detached. Shutting down.")
             error = EventHubError(str(shutdown), shutdown)
             self.close(exception=error)
             raise error
     except errors.MessageHandlerError as shutdown:
         if self.auto_reconnect:
             log.info("Sender detached. Attempting reconnect.")
             self.reconnect()
         else:
             log.info("Sender detached. Shutting down.")
             error = EventHubError(str(shutdown), shutdown)
             self.close(exception=error)
             raise error
     except Exception as e:
         log.info("Unexpected error occurred (%r).", e)
         raise EventHubError("Send failed: {}".format(e))
Beispiel #18
0
    def has_started(self):
        """
        Whether the handler has completed all start up processes such as
        establishing the connection, session, link and authentication, and
        is not ready to process messages.

        :rtype: bool
        """
        # pylint: disable=protected-access
        timeout = False
        auth_in_progress = False
        if self._handler._connection.cbs:
            timeout, auth_in_progress = self._handler._auth.handle_token()
        if timeout:
            raise EventHubError("Authorization timeout.")
        if auth_in_progress:
            return False
        if not self._handler._client_ready():
            return False
        return True
 def _error(outcome, condition):
     return None if outcome == constants.MessageSendResult.Ok else EventHubError(
         outcome, condition)