def open(self): """ Open the Receiver using the supplied conneciton. If the handler has previously been redirected, the redirect context will be used to create a new handler before opening it. :param connection: The underlying client shared connection. :type: connection: ~uamqp.connection.Connection """ # pylint: disable=protected-access self.running = True if self.redirected: self.source = self.redirected.address source = Source(self.source) if self.offset is not None: source.set_filter(self.offset.selector()) alt_creds = { "username": self.client._auth_config.get("iot_username"), "password":self.client._auth_config.get("iot_password")} 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()) self._handler.open() while not self._handler.client_ready(): time.sleep(0.05)
def _create_handler(self): source = Source(self._source) if self._offset is not None: source.set_filter(self._offset._selector()) # pylint:disable=protected-access if StrictVersion(uamqp.__version__) < StrictVersion("1.2.3"): # backward compatible until uamqp 1.2.3 released desired_capabilities = {} elif self._track_last_enqueued_event_properties: symbol_array = [types.AMQPSymbol(self._receiver_runtime_metric_symbol)] desired_capabilities = {"desired_capabilities": utils.data_factory(types.AMQPArray(symbol_array))} else: desired_capabilities = {"desired_capabilities": None} self._handler = ReceiveClientAsync( source, auth=self._client._create_auth(), # pylint:disable=protected-access debug=self._client._config.network_tracing, # pylint:disable=protected-access prefetch=self._prefetch, link_properties=self._link_properties, timeout=self._timeout, error_policy=self._retry_policy, keep_alive_interval=self._keep_alive, client_name=self._name, receive_settle_mode=uamqp.constants.ReceiverSettleMode.ReceiveAndDelete, auto_complete=False, properties=self._client._create_properties( # pylint:disable=protected-access self._client._config.user_agent), # pylint:disable=protected-access **desired_capabilities, # pylint:disable=protected-access loop=self._loop) self._messages_iter = None
def _create_handler(self, auth: "JWTTokenAsync") -> None: source = Source(self._source) if self._offset is not None: source.set_filter( event_position_selector(self._offset, self._offset_inclusive)) desired_capabilities = None if self._track_last_enqueued_event_properties: symbol_array = [types.AMQPSymbol(RECEIVER_RUNTIME_METRIC_SYMBOL)] desired_capabilities = utils.data_factory( types.AMQPArray(symbol_array)) properties = create_properties(self._client._config.user_agent # pylint:disable=protected-access ) self._handler = ReceiveClientAsync( source, auth=auth, debug=self._client._config.network_tracing, # pylint:disable=protected-access prefetch=self._prefetch, link_properties=self._link_properties, timeout=self._timeout, idle_timeout=self._idle_timeout, error_policy=self._retry_policy, keep_alive_interval=self._keep_alive, client_name=self._name, receive_settle_mode=uamqp.constants.ReceiverSettleMode. ReceiveAndDelete, auto_complete=False, properties=properties, desired_capabilities=desired_capabilities, loop=self._loop, ) self._handler._streaming_receive = True # pylint:disable=protected-access self._handler._message_received_callback = ( # pylint:disable=protected-access self._message_received)
def __init__( # pylint: disable=super-init-not-called self, client, source, offset=None, prefetch=300, epoch=None, keep_alive=None, auto_reconnect=True, loop=None): """ Instantiate an async receiver. :param client: The parent EventHubClientAsync. :type client: ~azure.eventhub.async_ops.EventHubClientAsync :param source: The source EventHub from which to receive events. :type source: ~uamqp.address.Source :param prefetch: The number of events to prefetch from the service for processing. Default is 300. :type prefetch: int :param epoch: An optional epoch value. :type epoch: int :param loop: An event loop. """ self.loop = loop or asyncio.get_event_loop() self.running = False self.client = client self.source = source self.offset = offset self.prefetch = prefetch self.epoch = epoch self.keep_alive = keep_alive self.auto_reconnect = auto_reconnect self.retry_policy = errors.ErrorPolicy(max_retries=3, on_error=_error_handler) self.reconnect_backoff = 1 self.redirected = None self.error = None self.properties = None partition = self.source.split('/')[-1] self.name = "EHReceiver-{}-partition{}".format(uuid.uuid4(), partition) source = Source(self.source) if self.offset is not None: source.set_filter(self.offset.selector()) if epoch: self.properties = { types.AMQPSymbol(self._epoch): types.AMQPLong(int(epoch)) } self._handler = ReceiveClientAsync( source, auth=self.client.get_auth(), 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(), loop=self.loop)
async def _reconnect_async(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")} await self._handler.close_async() source = Source(self.source) if self.offset is not None: source.set_filter(self.offset.selector()) self._handler = ReceiveClientAsync( 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(), loop=self.loop) try: await self._handler.open_async() while not await self._handler.client_ready_async(): await asyncio.sleep(0.05) return True except errors.TokenExpired as shutdown: log.info("AsyncReceiver disconnected due to token expiry. Shutting down.") error = EventHubError(str(shutdown), shutdown) await self.close_async(exception=error) raise error except (errors.LinkDetach, errors.ConnectionClose) as shutdown: if shutdown.action.retry and self.auto_reconnect: log.info("AsyncReceiver detached. Attempting reconnect.") return False log.info("AsyncReceiver detached. Shutting down.") error = EventHubError(str(shutdown), shutdown) await self.close_async(exception=error) raise error except errors.MessageHandlerError as shutdown: if self.auto_reconnect: log.info("AsyncReceiver detached. Attempting reconnect.") return False log.info("AsyncReceiver detached. Shutting down.") error = EventHubError(str(shutdown), shutdown) await self.close_async(exception=error) raise error except errors.AMQPConnectionError as shutdown: if str(shutdown).startswith("Unable to open authentication session") and self.auto_reconnect: log.info("AsyncReceiver couldn't authenticate. Attempting reconnect.") return False log.info("AsyncReceiver connection error (%r). Shutting down.", shutdown) error = EventHubError(str(shutdown)) await self.close_async(exception=error) raise error except Exception as e: log.info("Unexpected error occurred (%r). Shutting down.", e) error = EventHubError("Receiver reconnect failed: {}".format(e)) await self.close_async(exception=error) raise error
def add_receiver(self, consumer_group, partition, offset=None, prefetch=300): """ Add a receiver to the client for a particular consumer group and partition. :param consumer_group: The name of the consumer group. :type consumer_group: str :param partition: The ID of the partition. :type partition: str :param offset: The offset from which to start receiving. :type offset: ~azure.eventhub.Offset :param prefetch: The message prefetch count of the receiver. Default is 300. :type prefetch: int :returns: ~azure.eventhub.Receiver """ source_url = "amqps://{}{}/ConsumerGroups/{}/Partitions/{}".format( self.address.hostname, self.address.path, consumer_group, partition) source = Source(source_url) if offset is not None: source.set_filter(offset.selector()) handler = Receiver(self, source, prefetch=prefetch) self.clients.append(handler._handler) # pylint: disable=protected-access return handler
async def reconnect_async(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") } await self._handler.close_async() source = Source(self.source) if self.offset is not None: source.set_filter(self.offset.selector()) self._handler = ReceiveClientAsync( 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(), loop=self.loop) await self._handler.open_async() while not await self.has_started(): await self._handler._connection.work_async()
def _create_handler(self): alt_creds = { "username": self._client._auth_config.get("iot_username") if self._redirected else None, # pylint:disable=protected-access "password": self._client._auth_config.get("iot_password") if self._redirected else None # pylint:disable=protected-access } source = Source(self._source) if self._offset is not None: source.set_filter(self._offset._selector()) # pylint:disable=protected-access self._handler = ReceiveClient( source, auth=self._client._get_auth(**alt_creds), # pylint:disable=protected-access debug=self._client._config.network_tracing, # pylint:disable=protected-access prefetch=self._prefetch, link_properties=self._link_properties, timeout=self._timeout, error_policy=self._retry_policy, keep_alive_interval=self._keep_alive, client_name=self._name, properties=self._client._create_properties( # pylint:disable=protected-access self._client._config.user_agent)) # pylint:disable=protected-access self._messages_iter = None
def _open(self): """ Open the EventHubConsumer using the supplied connection. If the handler has previously been redirected, the redirect context will be used to create a new handler before opening it. """ # pylint: disable=protected-access self._check_closed() if self.redirected: self.client._process_redirect_uri(self.redirected) self.source = self.redirected.address source = Source(self.source) if self.offset is not None: source.set_filter(self.offset._selector()) alt_creds = { "username": self.client._auth_config.get("iot_username"), "password": self.client._auth_config.get("iot_password") } self._handler = ReceiveClient( source, auth=self.client.get_auth(**alt_creds), debug=self.client.config.network_tracing, 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( self.client.config.user_agent)) # pylint: disable=protected-access if not self.running: self._connect() self.running = True
def __init__(self, client, source, event_position=None, prefetch=300, owner_level=None, keep_alive=None, auto_reconnect=True): """ Instantiate a consumer. EventHubConsumer should be instantiated by calling the `create_consumer` method in EventHubClient. :param client: The parent EventHubClient. :type client: ~azure.eventhub.client.EventHubClient :param source: The source EventHub from which to receive events. :type source: str :param prefetch: The number of events to prefetch from the service for processing. Default is 300. :type prefetch: int :param owner_level: The priority of the exclusive consumer. It will an exclusive consumer if owner_level is set. :type owner_level: int """ self.running = False self.client = client self.source = source self.offset = event_position self.messages_iter = None self.prefetch = prefetch self.owner_level = owner_level self.keep_alive = keep_alive self.auto_reconnect = auto_reconnect self.retry_policy = errors.ErrorPolicy( max_retries=self.client.config.max_retries, on_error=_error_handler) self.reconnect_backoff = 1 self.properties = None self.redirected = None self.error = None partition = self.source.split('/')[-1] self.name = "EHReceiver-{}-partition{}".format(uuid.uuid4(), partition) source = Source(self.source) if self.offset is not None: source.set_filter(self.offset._selector()) # pylint: disable=protected-access if owner_level: self.properties = { types.AMQPSymbol(self._epoch): types.AMQPLong(int(owner_level)) } self._handler = ReceiveClient( source, auth=self.client.get_auth(), debug=self.client.config.network_tracing, 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( self.client.config.user_agent)) # pylint: disable=protected-access
def add_receiver(self, consumer_group, partition, offset=None, prefetch=300, operation=None): """ Add a receiver to the client for a particular consumer group and partition. :param consumer_group: The name of the consumer group. :type consumer_group: str :param partition: The ID of the partition. :type partition: str :param offset: The offset from which to start receiving. :type offset: ~azure.eventhub.common.Offset :param prefetch: The message prefetch count of the receiver. Default is 300. :type prefetch: int :operation: An optional operation to be appended to the hostname in the source URL. The value must start with `/` character. :type operation: str :rtype: ~azure.eventhub.receiver.Receiver """ path = self.address.path + operation if operation else self.address.path source_url = "amqps://{}{}/ConsumerGroups/{}/Partitions/{}".format( self.address.hostname, path, consumer_group, partition) source = Source(source_url) if offset is not None: source.set_filter(offset.selector()) handler = Receiver(self, source, prefetch=prefetch) self.clients.append(handler) return handler
def _get_source(self): # pylint: disable=protected-access if self._session: source = Source(self._entity_uri) session_filter = None if self._session_id == NEXT_AVAILABLE_SESSION else self._session_id source.set_filter(session_filter, name=SESSION_FILTER, descriptor=None) return source return self._entity_uri
async def reconnect_async(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") } await self._handler.close_async() source = Source(self.source) if self.offset is not None: source.set_filter(self.offset.selector()) self._handler = ReceiveClientAsync( 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(), loop=self.loop) try: await self._handler.open_async() while not await self.has_started(): await self._handler._connection.work_async() except (errors.LinkDetach, errors.ConnectionClose) as shutdown: if shutdown.action.retry and self.auto_reconnect: log.info("AsyncReceiver detached. Attempting reconnect.") await self.reconnect_async() else: log.info("AsyncReceiver detached. Shutting down.") error = EventHubError(str(shutdown), shutdown) await self.close_async(exception=error) raise error except errors.MessageHandlerError as shutdown: if self.auto_reconnect: log.info("AsyncReceiver detached. Attempting reconnect.") await self.reconnect_async() else: log.info("AsyncReceiver detached. Shutting down.") error = EventHubError(str(shutdown), shutdown) await self.close_async(exception=error) raise error except Exception as e: log.info("Unexpected error occurred (%r). Shutting down.", e) error = EventHubError("Receiver reconnect failed: {}".format(e)) await self.close_async(exception=error) raise error
def __init__( # pylint: disable=super-init-not-called self, client, source, offset=None, prefetch=300, epoch=None, keep_alive=None, auto_reconnect=True, loop=None): """ Instantiate an async receiver. :param client: The parent EventHubClientAsync. :type client: ~azure.eventhub.async_ops.EventHubClientAsync :param source: The source EventHub from which to receive events. :type source: ~uamqp.address.Source :param prefetch: The number of events to prefetch from the service for processing. Default is 300. :type prefetch: int :param epoch: An optional epoch value. :type epoch: int :param loop: An event loop. """ self.loop = loop or asyncio.get_event_loop() self.running = False self.client = client self.source = source self.offset = offset self.prefetch = prefetch self.epoch = epoch self.keep_alive = keep_alive self.auto_reconnect = auto_reconnect self.retry_policy = errors.ErrorPolicy(max_retries=3, on_error=_error_handler) self.reconnect_backoff = 1 self.redirected = None self.error = None self.properties = None partition = self.source.split('/')[-1] self.name = "EHReceiver-{}-partition{}".format(uuid.uuid4(), partition) source = Source(self.source) if self.offset is not None: source.set_filter(self.offset.selector()) if epoch: self.properties = {types.AMQPSymbol(self._epoch): types.AMQPLong(int(epoch))} self._handler = ReceiveClientAsync( source, auth=self.client.get_auth(), 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(), loop=self.loop)
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._handler.client_ready(): time.sleep(0.05) 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
async def open_async(self): """ Open the Receiver using the supplied conneciton. If the handler has previously been redirected, the redirect context will be used to create a new handler before opening it. :param connection: The underlying client shared connection. :type: connection: ~uamqp.async_ops.connection_async.ConnectionAsync Example: .. literalinclude:: ../examples/async_examples/test_examples_eventhub_async.py :start-after: [START eventhub_client_async_receiver_open] :end-before: [END eventhub_client_async_receiver_open] :language: python :dedent: 4 :caption: Open the Receiver using the supplied conneciton. """ # pylint: disable=protected-access self.running = True if self.redirected: self.source = self.redirected.address source = Source(self.source) if self.offset is not None: source.set_filter(self.offset.selector()) alt_creds = { "username": self.client._auth_config.get("iot_username"), "password":self.client._auth_config.get("iot_password")} self._handler = ReceiveClientAsync( 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(), loop=self.loop) await self._handler.open_async() while not await self._handler.client_ready_async(): await asyncio.sleep(0.05)
def _create_handler(self): alt_creds = { "username": self.client._auth_config.get("iot_username"), "password": self.client._auth_config.get("iot_password") } source = Source(self.source) if self.offset is not None: source.set_filter(self.offset._selector()) self._handler = ReceiveClientAsync( source, auth=self.client.get_auth(**alt_creds), debug=self.client.config.network_tracing, prefetch=self.prefetch, link_properties=self._link_properties, timeout=self.timeout, error_policy=self.retry_policy, keep_alive_interval=self.keep_alive, client_name=self.name, properties=self.client._create_properties( self.client.config.user_agent), # pylint: disable=protected-access loop=self.loop) self.messages_iter = None
def _get_source(self): source = Source(self.endpoint) session_filter = None if self.session_filter == NEXT_AVAILABLE else self.session_filter source.set_filter(session_filter, name=SESSION_FILTER, descriptor=None) return source
def _get_source(self): source = Source(self.endpoint) session_filter = None if self.session_filter == NEXT_AVAILABLE else self.session_filter source.set_filter(session_filter, name=SESSION_FILTER, descriptor=None) return source
def _build_connection(self, is_reconnect=False): """ :param is_reconnect: True - trying to reconnect after fail to connect or a connection is lost. False - the 1st time to connect :return: True - connected. False - not connected """ # pylint: disable=protected-access if is_reconnect: 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.config.network_tracing, 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( self.client.config.user_agent)) # pylint: disable=protected-access self.messages_iter = None try: self._handler.open() while not self._handler.client_ready(): time.sleep(0.05) return True except errors.AuthenticationException as shutdown: if is_reconnect: log.info( "EventHubConsumer couldn't authenticate. Shutting down. (%r)", shutdown) error = AuthenticationError(str(shutdown), shutdown) self.close(exception=error) raise error else: log.info( "EventHubConsumer couldn't authenticate. Attempting reconnect." ) return False except errors.LinkRedirect as redirect: self._redirect(redirect) return True except (errors.LinkDetach, errors.ConnectionClose) as shutdown: if shutdown.action.retry: log.info("EventHubConsumer detached. Attempting reconnect.") return False else: log.info("EventHubConsumer detached. Shutting down.") error = ConnectError(str(shutdown), shutdown) self.close(exception=error) raise error except errors.MessageHandlerError as shutdown: if is_reconnect: log.info("EventHubConsumer detached. Shutting down.") error = ConnectError(str(shutdown), shutdown) self.close(exception=error) raise error else: log.info("EventHubConsumer detached. Attempting reconnect.") return False except errors.AMQPConnectionError as shutdown: if is_reconnect: log.info( "EventHubConsumer connection error (%r). Shutting down.", shutdown) error = AuthenticationError(str(shutdown), shutdown) self.close(exception=error) raise error else: log.info( "EventHubConsumer couldn't authenticate. Attempting reconnect." ) return False except compat.TimeoutException as shutdown: if is_reconnect: log.info( "EventHubConsumer authentication timed out. Shutting down." ) error = AuthenticationError(str(shutdown), shutdown) self.close(exception=error) raise error else: log.info( "EventHubConsumer authentication timed out. Attempting reconnect." ) return False except Exception as e: log.error( "Unexpected error occurred when building connection (%r). Shutting down.", e) error = EventHubError( "Unexpected error occurred when building connection", e) self.close(exception=error) raise error
def _get_source(self): source = Source(self._entity_uri) session_filter = None if self._session_id == NEXT_AVAILABLE else self._session_id source.set_filter(session_filter, name=SESSION_FILTER, descriptor=None) return source