async def test_retry_put_block_with_seekable_stream_async(self, resource_group, location, storage_account, storage_account_key): pytest.skip("Aiohttp closes stream after request - cannot rewind.") # Arrange bsc = BlobServiceClient(self.account_url(storage_account.name, "blob"), credential=storage_account_key, retry_policy=self.retry, transport=AiohttpTestTransport()) await self._setup(bsc) blob_name = self.get_resource_name('blob') data = self.get_random_bytes(PUT_BLOCK_SIZE) data_stream = BytesIO(data) # rig the response so that it fails for a single time responder = ResponseCallback(status=201, new_status=408) # Act blob = bsc.get_blob_client(self.container_name, blob_name) await blob.stage_block(1, data_stream, raw_response_hook=responder.override_first_status) # Assert _, uncommitted_blocks = await blob.get_block_list( block_list_type="uncommitted", raw_response_hook=responder.override_first_status) self.assertEqual(len(uncommitted_blocks), 1) self.assertEqual(uncommitted_blocks[0].size, PUT_BLOCK_SIZE) # Commit block and verify content await blob.commit_block_list(['1'], raw_response_hook=responder.override_first_status) # Assert content = await (await blob.download_blob()).readall() self.assertEqual(content, data)
def test_retry_callback_and_retry_context(self, resource_group, location, storage_account, storage_account_key): # Arrange container_name = self.get_resource_name('utcontainer') retry = LinearRetry(backoff=1) service = self._create_storage_service(BlobServiceClient, storage_account, storage_account_key, retry_policy=retry) # Force the create call to 'timeout' with a 408 callback = ResponseCallback(status=201, new_status=408).override_status def assert_exception_is_present_on_retry_context(**kwargs): self.assertIsNotNone(kwargs.get('response')) self.assertEqual(kwargs['response'].status_code, 408) # Act try: # The initial create will return 201, but we overwrite it and retry. # The retry will then get a 409 and return false. with self.assertRaises(ResourceExistsError): service.create_container( container_name, raw_response_hook=callback, retry_hook=assert_exception_is_present_on_retry_context) finally: service.delete_container(container_name)
async def test_retry_with_deserialization_async(self, resource_group, location, storage_account, storage_account_key): # Arrange container_name = self.get_resource_name('retry') retry = ExponentialRetry(initial_backoff=1, increment_base=2) service = self._create_storage_service( BlobServiceClient, storage_account, storage_account_key, retry_policy=retry, transport=AiohttpTestTransport()) try: created = await service.create_container(container_name) # Act callback = ResponseCallback(status=200, new_status=408).override_first_status containers = service.list_containers(name_starts_with='retry', raw_response_hook=callback) # Assert listed = [] async for c in containers: listed.append(c) self.assertTrue(len(listed) >= 1) finally: await service.delete_container(container_name)
async def test_retry_callback_and_retry_context_async( self, tables_storage_account_name, tables_primary_storage_account_key): retry = LinearRetry(backoff=1) await self._set_up(tables_storage_account_name, tables_primary_storage_account_key, retry_policy=retry, default_table=False) new_table_name = self.get_resource_name('uttable') callback = ResponseCallback(status=201, new_status=408).override_status def assert_exception_is_present_on_retry_context(**kwargs): self.assertIsNotNone(kwargs.get('response')) self.assertEqual(kwargs['response'].status_code, 408) try: # The initial create will return 201, but we overwrite it with 408 and retry. # The retry will then get a 409 conflict. with pytest.raises(ResourceExistsError): await self.ts.create_table( new_table_name, raw_response_hook=callback, retry_hook=assert_exception_is_present_on_retry_context) finally: await self.ts.delete_table(new_table_name) await self._tear_down()
def test_exponential_retry(self, resource_group, location, storage_account, storage_account_key): # Arrange container_name = self.get_resource_name('utcontainer') retry = ExponentialRetry(initial_backoff=1, increment_base=3, retry_total=3) service = self._create_storage_service(BlobServiceClient, storage_account, storage_account_key, retry_policy=retry) try: container = service.create_container(container_name) # Force the create call to 'timeout' with a 408 callback = ResponseCallback(status=200, new_status=408) # Act with self.assertRaises(HttpResponseError): container.get_container_properties( raw_response_hook=callback.override_status) # Assert the response was called the right number of times (1 initial request + 3 retries) self.assertEqual(callback.count, 1 + 3) finally: # Clean up service.delete_container(container_name)
async def test_retry_put_block_with_non_seekable_stream_fail_async( self, resource_group, location, storage_account, storage_account_key): # Arrange bsc = BlobServiceClient(self.account_url(storage_account, "blob"), credential=storage_account_key, retry_policy=self.retry, transport=AiohttpTestTransport()) await self._setup(bsc) blob_name = self.get_resource_name('blob') data = self.get_random_bytes(PUT_BLOCK_SIZE) data_stream = self.NonSeekableStream(BytesIO(data)) # rig the response so that it fails for a single time responder = ResponseCallback(status=201, new_status=408) # Act blob = bsc.get_blob_client(self.container_name, blob_name) with self.assertRaises(HttpResponseError) as error: await blob.stage_block( 1, data_stream, length=PUT_BLOCK_SIZE, raw_response_hook=responder.override_first_status) # Assert self.assertEqual(error.exception.response.status_code, 408)
async def test_retry_on_server_error_async(self, tables_storage_account_name, tables_primary_storage_account_key): await self._set_up(tables_storage_account_name, tables_primary_storage_account_key, default_table=False) try: callback = ResponseCallback(status=201, new_status=500).override_status new_table_name = self.get_resource_name('uttable') # The initial create will return 201, but we overwrite it with 500 and retry. # The retry will then get a 409 conflict. with pytest.raises(ResourceExistsError): await self.ts.create_table(new_table_name, raw_response_hook=callback) finally: await self.ts.delete_table(new_table_name) await self._tear_down()
async def test_retry_on_timeout_async(self, tables_storage_account_name, tables_primary_storage_account_key): await self._set_up( tables_storage_account_name, tables_primary_storage_account_key, default_table=False, retry_mode=RetryMode.Exponential, retry_backoff_factor=1) callback = ResponseCallback(status=200, new_status=408).override_first_status try: # The initial create will return 201, but we overwrite it with 408 and retry. # The retry will then succeed. await self.ts.get_service_properties(raw_response_hook=callback) finally: await self._tear_down()
async def test_retry_on_server_error_async(self, resource_group, location, storage_account, storage_account_key): # Arrange container_name = self.get_resource_name('utcontainer') service = self._create_storage_service(BlobServiceClient, storage_account, storage_account_key, transport=AiohttpTestTransport()) # Force the create call to 'timeout' with a 408 callback = ResponseCallback(status=201, new_status=500).override_status # Act try: # The initial create will return 201, but we overwrite it and retry. # The retry will then get a 409 and return false. with self.assertRaises(ResourceExistsError): await service.create_container(container_name, raw_response_hook=callback) finally: await service.delete_container(container_name)
async def test_no_retry_async(self, tables_storage_account_name, tables_primary_storage_account_key): await self._set_up(tables_storage_account_name, tables_primary_storage_account_key, retry_total=0, default_table=False) new_table_name = self.get_resource_name('uttable') # Force the create call to error with a 500 callback = ResponseCallback(status=201, new_status=500).override_status try: with pytest.raises(HttpResponseError) as error: await self.ts.create_table(new_table_name, raw_response_hook=callback) assert error.value.response.status_code == 500 assert error.value.reason == 'Created' finally: await self.ts.delete_table(new_table_name) await self._tear_down()
async def test_retry_on_timeout_async(self, resource_group, location, storage_account, storage_account_key): # Arrange container_name = self.get_resource_name('utcontainer') retry = ExponentialRetry(initial_backoff=1, increment_base=2) service = self._create_storage_service( BlobServiceClient, storage_account, storage_account_key, retry_policy=retry, transport=AiohttpTestTransport()) callback = ResponseCallback(status=201, new_status=408).override_status # Act try: # The initial create will return 201, but we overwrite it and retry. # The retry will then get a 409 and return false. with self.assertRaises(ResourceExistsError): await service.create_container(container_name, raw_response_hook=callback) finally: await service.delete_container(container_name)
async def test_invalid_retry_async(self, resource_group, location, storage_account, storage_account_key): # Arrange container_name = self.get_resource_name('utcontainer') retry = ExponentialRetry(initial_backoff=1, increment_base=2) service = self._create_storage_service( BlobServiceClient, storage_account, storage_account_key, retry_policy=retry, transport=AiohttpTestTransport()) # Force the create call to fail by pretending it's a teapot callback = ResponseCallback(status=201, new_status=418).override_status # Act try: with self.assertRaises(HttpResponseError) as error: await service.create_container(container_name, raw_response_hook=callback) self.assertEqual(error.exception.response.status_code, 418) self.assertEqual(error.exception.reason, 'Created') finally: await service.delete_container(container_name)
async def test_no_retry_async(self, resource_group, location, storage_account, storage_account_key): # Arrange container_name = self.get_resource_name('utcontainer') service = self._create_storage_service( BlobServiceClient, storage_account, storage_account_key, retry_total=0, transport=AiohttpTestTransport()) # Force the create call to 'timeout' with a 408 callback = ResponseCallback(status=201, new_status=408).override_status # Act try: with self.assertRaises(HttpResponseError) as error: await service.create_container(container_name, raw_response_hook=callback) self.assertEqual(error.exception.response.status_code, 408) self.assertEqual(error.exception.reason, 'Created') finally: await service.delete_container(container_name)
async def test_retry_on_timeout_async(self, tables_storage_account_name, tables_primary_storage_account_key): retry = ExponentialRetry(initial_backoff=1, increment_base=2) await self._set_up(tables_storage_account_name, tables_primary_storage_account_key, retry_policy=retry, default_table=False) new_table_name = self.get_resource_name('uttable') callback = ResponseCallback(status=201, new_status=408).override_status try: # The initial create will return 201, but we overwrite it with 408 and retry. # The retry will then get a 409 conflict. with pytest.raises(ResourceExistsError): await self.ts.create_table(new_table_name, raw_response_hook=callback) finally: await self.ts.delete_table(new_table_name) await self._tear_down()
def test_linear_retry(self, resource_group, location, storage_account, storage_account_key): # Arrange container_name = self.get_resource_name('utcontainer') retry = LinearRetry(backoff=1) service = self._create_storage_service(BlobServiceClient, storage_account, storage_account_key, retry_policy=retry) # Force the create call to 'timeout' with a 408 callback = ResponseCallback(status=201, new_status=408).override_status # Act try: # The initial create will return 201, but we overwrite it and retry. # The retry will then get a 409 and return false. with self.assertRaises(ResourceExistsError): service.create_container(container_name, raw_response_hook=callback) finally: service.delete_container(container_name)
def test_retry_put_block_with_non_seekable_stream(self, resource_group, location, storage_account, storage_account_key): # Arrange bsc = BlobServiceClient(self.account_url(storage_account, "blob"), credential=storage_account_key, retry_policy=self.retry) self._setup(bsc) blob_name = self.get_resource_name('blob') data = self.get_random_bytes(PUT_BLOCK_SIZE) data_stream = self.NonSeekableStream(BytesIO(data)) # rig the response so that it fails for a single time responder = ResponseCallback(status=201, new_status=408) # Act blob = bsc.get_blob_client(self.container_name, blob_name) # Note: put_block transforms non-seekable streams into byte arrays before handing it off to the executor blob.stage_block(1, data_stream, raw_response_hook=responder.override_first_status) # Assert _, uncommitted_blocks = blob.get_block_list( block_list_type="uncommitted", raw_response_hook=responder.override_first_status) self.assertEqual(len(uncommitted_blocks), 1) self.assertEqual(uncommitted_blocks[0].size, PUT_BLOCK_SIZE) # Commit block and verify content blob.commit_block_list( ['1'], raw_response_hook=responder.override_first_status) # Assert content = blob.download_blob().readall() self.assertEqual(content, data)
def test_retry_with_deserialization(self, resource_group, location, storage_account, storage_account_key): # Arrange container_name = self.get_resource_name('retry') retry = ExponentialRetry(initial_backoff=1, increment_base=2) service = self._create_storage_service(BlobServiceClient, storage_account, storage_account_key, retry_policy=retry) try: created = service.create_container(container_name) # Act callback = ResponseCallback(status=200, new_status=408).override_first_status containers = service.list_containers(name_starts_with='retry', raw_response_hook=callback) # Assert containers = list(containers) self.assertTrue(len(containers) >= 1) finally: service.delete_container(container_name)