internal async Task <Response <Stream> > DownloadStreamingInternal(Uri sourceEndpoint, HttpRange range, bool async, CancellationToken cancellationToken) { Argument.AssertNotNull(sourceEndpoint, nameof(sourceEndpoint)); Response <Stream> response; if (async) { response = await StartDownloadAsync(sourceEndpoint, range, cancellationToken : cancellationToken).ConfigureAwait(false); } else { response = StartDownload(sourceEndpoint, range, cancellationToken: cancellationToken); } Stream stream = RetriableStream.Create( response.Value, startOffset => StartDownload(sourceEndpoint, range, startOffset, cancellationToken).Value, async startOffset => (await StartDownloadAsync(sourceEndpoint, range, startOffset, cancellationToken).ConfigureAwait(false)).Value, _client._pipeline.ResponseClassifier, Constants.ContentDownloader.RetriableStreamRetries ); return(Response.FromValue(stream, response.GetRawResponse())); }
public async Task DoesntRetryNonRetryableExceptions() { var stream1 = new MockReadStream(100, throwAfter: 50); var stream2 = new MockReadStream(50, offset: 50, throwAfter: 0, throwIOException: false); var mockTransport = new MockTransport( new MockResponse(200) { ContentStream = stream1 }, new MockResponse(200) { ContentStream = stream2 } ); var pipeline = new HttpPipeline(mockTransport); var reliableStream = await RetriableStream.Create(offset => SendTestRequestAsync(pipeline, offset), new ResponseClassifier(), maxRetries : 5); Assert.AreEqual(25, await reliableStream.ReadAsync(_buffer, 0, 25)); Assert.AreEqual(100, reliableStream.Length); Assert.AreEqual(25, reliableStream.Position); Assert.AreEqual(25, await reliableStream.ReadAsync(_buffer, 25, 25)); Assert.AreEqual(100, reliableStream.Length); Assert.AreEqual(50, reliableStream.Position); Assert.ThrowsAsync <InvalidOperationException>(() => reliableStream.ReadAsync(_buffer, 50, 50)); AssertReads(_buffer, 50); }
public async Task DoesntCallLengthPrematurely() { var stream1 = new NoLengthStream(); var stream2 = new MockReadStream(50); var mockTransport = new MockTransport( new MockResponse(200) { ContentStream = stream1 }, new MockResponse(200) { ContentStream = stream2 } ); var pipeline = new HttpPipeline(mockTransport); var reliableStream = RetriableStream.Create(await SendTestRequestAsync(pipeline, 0), offset => SendTestRequestAsync(pipeline, offset), new ResponseClassifier(), maxRetries: 5); Assert.AreEqual(50, await reliableStream.ReadAsync(_buffer, 0, 50)); Assert.AreEqual(50, reliableStream.Position); Assert.AreEqual(0, await reliableStream.ReadAsync(_buffer, 0, 50)); Assert.Throws <NotSupportedException>(() => _ = reliableStream.Length); AssertReads(_buffer, 50); }
public async Task MaintainsGlobalLengthAndPosition() { var stream1 = new MockReadStream(100, throwAfter: 50); var stream2 = new MockReadStream(50, offset: 50, throwIOException: false); var mockTransport = new MockTransport( new MockResponse(200) { ContentStream = stream1 }, new MockResponse(200) { ContentStream = stream2 } ); var pipeline = new HttpPipeline(mockTransport); var reliableStream = await RetriableStream.Create(offset => SendTestRequestAsync(pipeline, offset), new ResponseClassifier(), maxRetries : 5); Assert.AreEqual(25, await reliableStream.ReadAsync(_buffer, 0, 25)); Assert.AreEqual(100, reliableStream.Length); Assert.AreEqual(25, reliableStream.Position); Assert.AreEqual(25, await reliableStream.ReadAsync(_buffer, 25, 25)); Assert.AreEqual(100, reliableStream.Length); Assert.AreEqual(50, reliableStream.Position); Assert.AreEqual(50, await reliableStream.ReadAsync(_buffer, 50, 50)); Assert.AreEqual(100, reliableStream.Length); Assert.AreEqual(100, reliableStream.Position); Assert.AreEqual(0, await reliableStream.ReadAsync(_buffer, 0, 50)); AssertReads(_buffer, 100); }
public async Task ThrowsIfSendingRetryRequestThrows() { var stream1 = new MockReadStream(100, throwAfter: 50); var mockTransport = new MockTransport(new MockResponse(200) { ContentStream = stream1 }); var pipeline = new HttpPipeline(mockTransport); var reliableStream = await RetriableStream.Create( async offset => { if (offset == 0) { return(await SendTestRequestAsync(pipeline, offset)); } else { throw new InvalidOperationException(); } }, new ResponseClassifier(), maxRetries : 5); await reliableStream.ReadAsync(_buffer, 0, 25); await reliableStream.ReadAsync(_buffer, 25, 25); AssertReads(_buffer, 50); Assert.ThrowsAsync <InvalidOperationException>(() => reliableStream.ReadAsync(_buffer, 50, 50)); }
private Task <Stream> CreateAsync( Func <long, Response> responseFactory, Func <long, Task <Response> > asyncResponseFactory, ResponseClassifier responseClassifier, int maxRetries) { return(IsAsync ? RetriableStream.CreateAsync(responseFactory, asyncResponseFactory, responseClassifier, maxRetries) : Task.FromResult(RetriableStream.Create(responseFactory, asyncResponseFactory, responseClassifier, maxRetries))); }
public async Task RetriesMaxCountAndThrowsAggregateException() { var mockTransport = new MockTransport( new MockResponse(200) { ContentStream = new MockReadStream(100, throwAfter: 1) }, new MockResponse(200) { ContentStream = new MockReadStream(100, throwAfter: 1, offset: 1) }, new MockResponse(200) { ContentStream = new MockReadStream(100, throwAfter: 1, offset: 2) }, new MockResponse(200) { ContentStream = new MockReadStream(100, throwAfter: 1, offset: 3) } ); var pipeline = new HttpPipeline(mockTransport); var reliableStream = await RetriableStream.Create( async offset => { if (offset == 0) { return(await SendTestRequestAsync(pipeline, offset)); } throw new InvalidOperationException(); }, new ResponseClassifier(), maxRetries : 3); var aggregateException = Assert.ThrowsAsync <AggregateException>(() => reliableStream.ReadAsync(_buffer, 0, 4)); StringAssert.StartsWith("Retry failed after 4 tries", aggregateException.Message); Assert.AreEqual(4, aggregateException.InnerExceptions.Count); Assert.AreEqual("Failed at 0", aggregateException.InnerExceptions[0].Message); Assert.AreEqual("Failed at 1", aggregateException.InnerExceptions[1].Message); Assert.AreEqual("Failed at 2", aggregateException.InnerExceptions[2].Message); Assert.AreEqual("Failed at 3", aggregateException.InnerExceptions[3].Message); Assert.AreEqual(4, mockTransport.Requests.Count); }
public void ThrowsForLengthOnNonSeekableStream() { Assert.Throws <NotSupportedException>(() => _ = RetriableStream.Create( _ => new MockReadStream(100, canSeek: false), _ => default,