async def test_async_session_by_conn_str_receive_handler_with_autolockrenew( self, servicebus_namespace_connection_string, servicebus_queue, **kwargs): async with ServiceBusClient.from_connection_string( servicebus_namespace_connection_string, logging_enable=False) as sb_client: session_id = str(uuid.uuid4()) async with sb_client.get_queue_sender( servicebus_queue.name) as sender: for i in range(10): message = Message("{}".format(i), session_id=session_id) await sender.send(message) renewer = AutoLockRenew() messages = [] async with sb_client.get_queue_session_receiver( servicebus_queue.name, session_id=session_id, idle_timeout=5, mode=ReceiveSettleMode.PeekLock, prefetch=20) as session: renewer.register(session.session, timeout=60) print("Registered lock renew thread", session.session.locked_until_utc, utc_now()) with pytest.raises(SessionLockExpired): async for message in session: if not messages: await asyncio.sleep(45) print("First sleep {}".format( session.session.locked_until_utc - utc_now())) assert not session.session.expired with pytest.raises(TypeError): message.expired assert message.locked_until_utc is None with pytest.raises(TypeError): await message.renew_lock() assert message.lock_token is not None await message.complete() messages.append(message) elif len(messages) == 1: await asyncio.sleep(45) print("Second sleep {}".format( session.session.locked_until_utc - utc_now())) assert session.session.expired assert isinstance(session.session.auto_renew_error, AutoLockRenewTimeout) try: await message.complete() raise AssertionError( "Didn't raise SessionLockExpired") except SessionLockExpired as e: assert isinstance(e.inner_exception, AutoLockRenewTimeout) messages.append(message) await renewer.shutdown() assert len(messages) == 2
def test_session_by_servicebus_client_renew_client_locks( self, servicebus_namespace_connection_string, servicebus_queue, **kwargs): with ServiceBusClient.from_connection_string( servicebus_namespace_connection_string, logging_enable=False) as sb_client: session_id = str(uuid.uuid4()) messages = [] locks = 3 with sb_client.get_queue_receiver(servicebus_queue.name, session_id=session_id, prefetch=10) as receiver: with sb_client.get_queue_sender( servicebus_queue.name) as sender: for i in range(locks): message = Message("Test message no. {}".format(i), session_id=session_id) sender.send(message) messages.extend(receiver.receive()) recv = True while recv: recv = receiver.receive(max_wait_time=5) messages.extend(recv) try: for m in messages: with pytest.raises(TypeError): expired = m.expired assert m.locked_until_utc is None assert m.lock_token is not None time.sleep(5) initial_expiry = receiver.session._locked_until_utc receiver.session.renew_lock() assert (receiver.session._locked_until_utc - initial_expiry) >= timedelta(seconds=5) finally: messages[0].complete() messages[1].complete() # This magic number is because of a 30 second lock renewal window. Chose 31 seconds because at 30, you'll see "off by .05 seconds" flaky failures # potentially as a side effect of network delays/sleeps/"typical distributed systems nonsense." In a perfect world we wouldn't have a magic number/network hop but this allows # a slightly more robust test in absence of that. assert (receiver.session._locked_until_utc - utc_now()) <= timedelta(seconds=60) time.sleep((receiver.session._locked_until_utc - utc_now()).total_seconds()) with pytest.raises(SessionLockExpired): messages[2].complete()
def test_session_schedule_message(self, servicebus_namespace_connection_string, servicebus_queue, **kwargs): with ServiceBusClient.from_connection_string( servicebus_namespace_connection_string, logging_enable=False) as sb_client: session_id = str(uuid.uuid4()) enqueue_time = (utc_now() + timedelta(minutes=2)).replace(microsecond=0) with sb_client.get_queue_session_receiver(servicebus_queue.name, session_id=session_id) as receiver: with sb_client.get_queue_sender(servicebus_queue.name) as sender: content = str(uuid.uuid4()) message_id = uuid.uuid4() message = Message(content, session_id=session_id) message.properties.message_id = message_id message.schedule(enqueue_time) sender.send(message) messages = [] count = 0 while not messages and count < 12: messages = receiver.receive(max_wait_time=10) receiver.session.renew_lock() count += 1 data = str(messages[0]) assert data == content assert messages[0].properties.message_id == message_id assert messages[0].scheduled_enqueue_time_utc == enqueue_time assert messages[0].scheduled_enqueue_time_utc == messages[0].enqueued_time_utc.replace(microsecond=0) assert len(messages) == 1
async def test_async_session_cancel_scheduled_messages(self, servicebus_namespace_connection_string, servicebus_queue, **kwargs): async with ServiceBusClient.from_connection_string( servicebus_namespace_connection_string, logging_enable=False) as sb_client: session_id = str(uuid.uuid4()) enqueue_time = (utc_now() + timedelta(minutes=2)).replace(microsecond=0) async with sb_client.get_queue_sender(servicebus_queue.name) as sender: message_a = Message("Test scheduled message", session_id=session_id) message_b = Message("Test scheduled message", session_id=session_id) tokens = await sender.schedule_messages([message_a, message_b], enqueue_time) assert len(tokens) == 2 await sender.cancel_scheduled_messages(tokens) renewer = AutoLockRenew() messages = [] async with sb_client.get_queue_session_receiver(servicebus_queue.name, session_id=session_id) as receiver: renewer.register(receiver.session, timeout=140) messages.extend(await receiver.receive_messages(max_wait_time=120)) messages.extend(await receiver.receive_messages(max_wait_time=5)) try: assert len(messages) == 0 except AssertionError: for m in messages: print(str(m)) await m.complete() raise await renewer.close()
async def test_async_session_schedule_multiple_messages(self, servicebus_namespace_connection_string, servicebus_queue, **kwargs): async with ServiceBusClient.from_connection_string( servicebus_namespace_connection_string, logging_enable=False) as sb_client: import uuid session_id = str(uuid.uuid4()) enqueue_time = (utc_now() + timedelta(minutes=2)).replace(microsecond=0) messages = [] async with sb_client.get_queue_sender(servicebus_queue.name) as sender: content = str(uuid.uuid4()) message_id_a = uuid.uuid4() message_a = Message(content, session_id=session_id) message_a.message_id = message_id_a message_id_b = uuid.uuid4() message_b = Message(content, session_id=session_id) message_b.message_id = message_id_b tokens = await sender.schedule_messages([message_a, message_b], enqueue_time) assert len(tokens) == 2 renewer = AutoLockRenew() async with sb_client.get_queue_session_receiver(servicebus_queue.name, session_id=session_id, prefetch_count=20) as receiver: renewer.register(receiver.session, timeout=140) messages.extend(await receiver.receive_messages(max_wait_time=120)) messages.extend(await receiver.receive_messages(max_wait_time=5)) if messages: data = str(messages[0]) assert data == content assert messages[0].message_id in (message_id_a, message_id_b) assert messages[0].scheduled_enqueue_time_utc == enqueue_time assert messages[0].scheduled_enqueue_time_utc == messages[0].enqueued_time_utc.replace(microsecond=0) assert len(messages) == 2 else: raise Exception("Failed to receive schdeduled message.") await renewer.close()
def test_session_schedule_multiple_messages(self, servicebus_namespace_connection_string, servicebus_queue, **kwargs): with ServiceBusClient.from_connection_string( servicebus_namespace_connection_string, logging_enable=False) as sb_client: session_id = str(uuid.uuid4()) enqueue_time = (utc_now() + timedelta(minutes=2)).replace(microsecond=0) with sb_client.get_queue_session_receiver(servicebus_queue.name, session_id=session_id, prefetch=20) as receiver: with sb_client.get_queue_sender(servicebus_queue.name) as sender: content = str(uuid.uuid4()) message_id_a = uuid.uuid4() message_a = Message(content, session_id=session_id) message_a.properties.message_id = message_id_a message_id_b = uuid.uuid4() message_b = Message(content, session_id=session_id) message_b.properties.message_id = message_id_b tokens = sender.schedule(enqueue_time, message_a, message_b) assert len(tokens) == 2 messages = [] count = 0 while len(messages) < 2 and count < 12: receiver.session.renew_lock() messages = receiver.receive(max_wait_time=15) time.sleep(5) count += 1 data = str(messages[0]) assert data == content assert messages[0].properties.message_id in (message_id_a, message_id_b) assert messages[0].scheduled_enqueue_time_utc == enqueue_time assert messages[0].scheduled_enqueue_time_utc == messages[0].enqueued_time_utc.replace(microsecond=0) assert len(messages) == 2
async def test_async_session_schedule_message(self, servicebus_namespace_connection_string, servicebus_queue, **kwargs): async with ServiceBusClient.from_connection_string( servicebus_namespace_connection_string, logging_enable=False) as sb_client: import uuid session_id = str(uuid.uuid4()) enqueue_time = (utc_now() + timedelta(minutes=2)).replace(microsecond=0) async with sb_client.get_queue_sender(servicebus_queue.name) as sender: content = str(uuid.uuid4()) message_id = uuid.uuid4() message = Message(content, session_id=session_id) message.properties.message_id = message_id message.scheduled_enqueue_time_utc = enqueue_time await sender.send_messages(message) messages = [] renewer = AutoLockRenew() async with sb_client.get_queue_session_receiver(servicebus_queue.name, session_id=session_id) as receiver: renewer.register(receiver.session, timeout=140) messages.extend(await receiver.receive_messages(max_wait_time=120)) messages.extend(await receiver.receive_messages(max_wait_time=5)) if messages: data = str(messages[0]) assert data == content assert messages[0].properties.message_id == message_id assert messages[0].scheduled_enqueue_time_utc == enqueue_time assert messages[0].scheduled_enqueue_time_utc == messages[0].enqueued_time_utc.replace(microsecond=0) assert len(messages) == 1 else: raise Exception("Failed to receive schdeduled message.") await renewer.shutdown()
def test_session_by_servicebus_client_list_sessions_with_receiver( self, servicebus_namespace_connection_string, servicebus_queue, **kwargs): with ServiceBusClient.from_connection_string( servicebus_namespace_connection_string, logging_enable=False) as sb_client: sessions = [] start_time = utc_now() for i in range(5): sessions.append(str(uuid.uuid4())) for session_id in sessions: with sb_client.get_queue_sender( servicebus_queue.name) as sender: for i in range(5): message = Message("Test message no. {}".format(i), session_id=session_id) sender.send(message) for session_id in sessions: with sb_client.get_queue_receiver( servicebus_queue.name, session_id=session_id) as receiver: receiver.set_session_state("SESSION {}".format(session_id)) with sb_client.get_queue_receiver( servicebus_queue.name, session_id=NEXT_AVAILABLE, idle_timeout=5, mode=ReceiveSettleMode.PeekLock) as receiver: current_sessions = receiver.list_sessions( updated_since=start_time) assert len(current_sessions) == 5 assert current_sessions == sessions
def test_session_cancel_scheduled_messages( self, servicebus_namespace_connection_string, servicebus_queue, **kwargs): with ServiceBusClient.from_connection_string( servicebus_namespace_connection_string, logging_enable=False) as sb_client: session_id = str(uuid.uuid4()) enqueue_time = (utc_now() + timedelta(minutes=2)).replace(microsecond=0) with sb_client.get_queue_sender(servicebus_queue.name) as sender: message_a = Message("Test scheduled message", session_id=session_id) message_b = Message("Test scheduled message", session_id=session_id) tokens = sender.schedule(enqueue_time, message_a, message_b) assert len(tokens) == 2 sender.cancel_scheduled_messages(*tokens) with sb_client.get_queue_receiver( servicebus_queue.name, session_id=session_id) as receiver: messages = [] count = 0 while not messages and count < 13: messages = receiver.receive(max_wait_time=10) receiver.session.renew_lock() count += 1 assert len(messages) == 0
async def test_async_session_by_servicebus_client_list_sessions_with_client( self, servicebus_namespace_connection_string, servicebus_queue, **kwargs): async with ServiceBusClient.from_connection_string( servicebus_namespace_connection_string, logging_enable=False) as sb_client: sessions = [] start_time = utc_now() for i in range(5): sessions.append(str(uuid.uuid4())) for session in sessions: async with sb_client.get_queue_sender( servicebus_queue.name) as sender: for i in range(5): message = Message("Test message no. {}".format(i), session_id=session) await sender.send(message) for session in sessions: async with sb_client.get_queue_session_receiver( servicebus_queue.name, session_id=session) as receiver: await receiver.session.set_session_state( "SESSION {}".format(session)) current_sessions = await sb_client.list_sessions( updated_since=start_time) assert len(current_sessions) == 5 assert current_sessions == sessions
async def test_async_session_by_conn_str_receive_handler_with_autolockrenew(self, servicebus_namespace_connection_string, servicebus_queue, **kwargs): async with ServiceBusClient.from_connection_string( servicebus_namespace_connection_string, logging_enable=False) as sb_client: session_id = str(uuid.uuid4()) async with sb_client.get_queue_sender(servicebus_queue.name) as sender: for i in range(10): message = Message("{}".format(i), session_id=session_id) await sender.send_messages(message) results = [] async def lock_lost_callback(renewable, error): results.append(renewable) renewer = AutoLockRenew() messages = [] async with sb_client.get_queue_session_receiver(servicebus_queue.name, session_id=session_id, max_wait_time=5, receive_mode=ReceiveMode.PeekLock, prefetch_count=20) as session: renewer.register(session.session, timeout=60) print("Registered lock renew thread", session.session.locked_until_utc, utc_now()) with pytest.raises(SessionLockExpired): async for message in session: if not messages: await asyncio.sleep(45) print("First sleep {}".format(session.session.locked_until_utc - utc_now())) assert not session.session._lock_expired with pytest.raises(TypeError): message._lock_expired assert message.locked_until_utc is None with pytest.raises(TypeError): await message.renew_lock() assert message.lock_token is not None await message.complete() messages.append(message) elif len(messages) == 1: assert not results await asyncio.sleep(45) print("Second sleep {}".format(session.session.locked_until_utc - utc_now())) assert session.session._lock_expired assert isinstance(session.session.auto_renew_error, AutoLockRenewTimeout) try: await message.complete() raise AssertionError("Didn't raise SessionLockExpired") except SessionLockExpired as e: assert isinstance(e.inner_exception, AutoLockRenewTimeout) messages.append(message) # While we're testing autolockrenew and sessions, let's make sure we don't call the lock-lost callback when a session exits. renewer._renew_period = 1 session = None async with sb_client.get_queue_session_receiver(servicebus_queue.name, session_id=session_id, max_wait_time=5, receive_mode=ReceiveMode.PeekLock, prefetch_count=10) as receiver: session = receiver.session renewer.register(session, timeout=5, on_lock_renew_failure=lock_lost_callback) await asyncio.sleep(max(0,(session.locked_until_utc - utc_now()).total_seconds()+1)) # If this pattern repeats make sleep_until_expired_async assert not results await renewer.close() assert len(messages) == 2
def __init__(self, prevent_renew_lock=False, exception_on_renew_lock=False): self._lock_duration = 2 self._received_timestamp_utc = utc_now() self.locked_until_utc = self._received_timestamp_utc + timedelta(seconds=self._lock_duration) self._settled = False self._receiver = MockReceiver() self._prevent_renew_lock = prevent_renew_lock self._exception_on_renew_lock = exception_on_renew_lock
async def test_async_mgmt_queue_create_by_name( self, servicebus_namespace_connection_string, **kwargs): mgmt_service = ServiceBusManagementClient.from_connection_string( servicebus_namespace_connection_string) queue_name = "eidk" created_at = utc_now() await mgmt_service.create_queue(queue_name) queue = await mgmt_service.get_queue(queue_name) assert queue.queue_name == queue_name assert queue.entity_availability_status == 'Available' assert queue.status == 'Active'
def __init__(self, prevent_renew_lock=False, exception_on_renew_lock=False, **kwargs): self._lock_duration = kwargs.get("lock_duration", 2) self._raw_amqp_message = None self._received_timestamp_utc = utc_now() self.locked_until_utc = self._received_timestamp_utc + timedelta( seconds=self._lock_duration) self._settled = False self._receiver = MockReceiver() self._prevent_renew_lock = prevent_renew_lock self._exception_on_renew_lock = exception_on_renew_lock
def test_mgmt_queue_create_by_name(self, servicebus_namespace_connection_string, **kwargs): mgmt_service = ServiceBusAdministrationClient.from_connection_string(servicebus_namespace_connection_string) clear_queues(mgmt_service) queue_name = "queue_testaddf" mgmt_service.create_queue(queue_name) created_at_utc = utc_now() try: queue = mgmt_service.get_queue(queue_name) assert queue.name == queue_name assert queue.availability_status == 'Available' assert queue.status == 'Active' # assert created_at_utc < queue.created_at_utc < utc_now() + datetime.timedelta(minutes=10) finally: mgmt_service.delete_queue(queue_name)
def test_mgmt_queue_create_by_name(self, servicebus_namespace_connection_string, **kwargs): mgmt_service = ServiceBusManagementClient.from_connection_string(servicebus_namespace_connection_string) clear_queues(mgmt_service) queue_name = "queue_testaddf" mgmt_service.create_queue(queue_name) created_at = utc_now() try: queue = mgmt_service.get_queue(queue_name) assert queue.name == queue_name assert queue.entity_availability_status == 'Available' assert queue.status == 'Active' # assert created_at < queue.created_at < utc_now() + datetime.timedelta(minutes=10) # TODO: Should be created_at_utc for consistency with dataplane. finally: mgmt_service.delete_queue(queue_name)
async def test_async_mgmt_queue_create_by_name( self, servicebus_namespace_connection_string, **kwargs): mgmt_service = ServiceBusAdministrationClient.from_connection_string( servicebus_namespace_connection_string) await clear_queues(mgmt_service) queue_name = "eidk" created_at = utc_now() await mgmt_service.create_queue(queue_name) try: queue = await mgmt_service.get_queue(queue_name) assert queue.name == queue_name assert queue.availability_status == 'Available' assert queue.status == 'Active' # assert created_at < queue.created_at < utc_now() + datetime.timedelta(minutes=10) # TODO: Should be created_at_utc for consistency with dataplane. finally: await mgmt_service.delete_queue(queue_name)
def sleep_until_expired(entity): time.sleep(max(0,(entity.locked_until_utc - utc_now()).total_seconds()+1))
def _lock_expired(self): if self.locked_until_utc and self.locked_until_utc <= utc_now(): return True return False