Skip to content

Commit d664bd7

Browse files
committed
remove downloadexception field
1 parent 8778d34 commit d664bd7

File tree

3 files changed

+30
-102
lines changed

3 files changed

+30
-102
lines changed

sdk/src/Services/S3/Custom/Transfer/Internal/IDownloadManager.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,6 @@ internal interface IDownloadManager : IDisposable
5555
/// with the previous two-method API.
5656
/// </remarks>
5757
Task<DownloadResult> StartDownloadAsync(EventHandler<WriteObjectProgressArgs> progressCallback, CancellationToken cancellationToken);
58-
59-
/// <summary>
60-
/// Exception that occurred during downloads, if any.
61-
/// </summary>
62-
Exception DownloadException { get; }
6358
}
6459

6560
/// <summary>

sdk/src/Services/S3/Custom/Transfer/Internal/MultipartDownloadManager.cs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ internal class MultipartDownloadManager : IDownloadManager
4646
private readonly SemaphoreSlim _httpConcurrencySlots;
4747
private readonly bool _ownsHttpThrottler;
4848
private readonly RequestEventHandler _requestEventHandler;
49-
50-
private Exception _downloadException;
5149
private bool _disposed = false;
5250
private bool _discoveryCompleted = false;
5351
private Task _downloadCompletionTask;
@@ -166,15 +164,6 @@ public MultipartDownloadManager(IAmazonS3 s3Client, BaseDownloadRequest request,
166164
}
167165
}
168166

169-
/// <inheritdoc/>
170-
public Exception DownloadException
171-
{
172-
get
173-
{
174-
return _downloadException;
175-
}
176-
}
177-
178167
/// <summary>
179168
/// Discovers the download strategy and starts concurrent downloads in a single unified operation.
180169
/// This eliminates resource leakage by managing HTTP slots and buffer capacity internally.
@@ -259,7 +248,6 @@ private async Task<DownloadResult> PerformDiscoveryAsync(CancellationToken cance
259248
}
260249
catch (Exception ex)
261250
{
262-
_downloadException = ex;
263251
_logger.Error(ex, "MultipartDownloadManager: Discovery failed");
264252
throw;
265253
}
@@ -336,7 +324,6 @@ private async Task PerformDownloadsAsync(DownloadResult downloadResult, EventHan
336324
}
337325
catch (Exception ex)
338326
{
339-
_downloadException = ex;
340327
_logger.Error(ex, "MultipartDownloadManager: Download failed");
341328

342329
HandleDownloadError(ex, internalCts);
@@ -431,7 +418,6 @@ private async Task StartBackgroundDownloadsAsync(DownloadResult downloadResult,
431418
#pragma warning disable CA1031 // Do not catch general exception types
432419
catch (Exception ex)
433420
{
434-
_downloadException = ex;
435421
HandleDownloadError(ex, internalCts);
436422
throw;
437423
}

sdk/test/Services/S3/UnitTests/Custom/MultipartDownloadManagerTests.cs

Lines changed: 30 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ public void Constructor_WithValidParameters_CreatesCoordinator()
130130

131131
// Assert
132132
Assert.IsNotNull(coordinator);
133-
Assert.IsNull(coordinator.DownloadException);
134133
}
135134

136135
[DataTestMethod]
@@ -192,26 +191,6 @@ public void Constructor_WithEncryptionClient_ExceptionMessageIsDescriptive()
192191

193192
#endregion
194193

195-
#region Property Tests
196-
197-
[TestMethod]
198-
public void DownloadException_InitiallyNull()
199-
{
200-
// Arrange
201-
var mockClient = MultipartDownloadTestHelpers.CreateMockS3Client();
202-
var request = MultipartDownloadTestHelpers.CreateOpenStreamRequest();
203-
var config = MultipartDownloadTestHelpers.CreateBufferedDownloadConfiguration();
204-
var coordinator = new MultipartDownloadManager(mockClient.Object, request, config, CreateMockDataHandler().Object);
205-
206-
// Act
207-
var exception = coordinator.DownloadException;
208-
209-
// Assert
210-
Assert.IsNull(exception);
211-
}
212-
213-
#endregion
214-
215194
#region Discovery - PART Strategy - Single Part Tests
216195

217196
[TestMethod]
@@ -1156,8 +1135,6 @@ public async Task StartDownloadsAsync_BackgroundTaskSuccess_DisposesCancellation
11561135
!coordinator.DownloadCompletionTask.IsCanceled,
11571136
"Background task should complete successfully");
11581137

1159-
Assert.IsNull(coordinator.DownloadException,
1160-
"No download exception should occur");
11611138
}
11621139

11631140
[TestMethod]
@@ -1217,10 +1194,8 @@ public async Task StartDownloadsAsync_BackgroundTaskFailure_DisposesCancellation
12171194
// Assert - Background task should have failed but cleanup should be done
12181195
Assert.IsTrue(coordinator.DownloadCompletionTask.IsCompleted,
12191196
"Background task should be completed (even with failure)");
1220-
Assert.IsNotNull(coordinator.DownloadException,
1221-
"Download exception should be captured");
1222-
Assert.IsInstanceOfType(coordinator.DownloadException, typeof(InvalidOperationException),
1223-
"Should capture the simulated failure");
1197+
Assert.IsTrue(coordinator.DownloadCompletionTask.IsFaulted,
1198+
"Background task should be faulted");
12241199
}
12251200

12261201
[TestMethod]
@@ -1270,8 +1245,7 @@ public async Task StartDownloadsAsync_EarlyError_DisposesCancellationTokenSource
12701245
Assert.AreEqual("Simulated prepare failure", ex.Message);
12711246
}
12721247

1273-
// Assert - Exception should be captured and no background task should exist
1274-
Assert.IsNotNull(coordinator.DownloadException, "Download exception should be captured");
1248+
// Assert - DownloadCompletionTask should return completed task when no background work exists
12751249
Assert.IsTrue(coordinator.DownloadCompletionTask.IsCompleted,
12761250
"DownloadCompletionTask should return completed task when no background work exists");
12771251
}
@@ -1341,8 +1315,8 @@ public async Task StartDownloadsAsync_BackgroundTaskCancellation_HandlesTokenDis
13411315
// Assert - Cancellation should be handled properly with cleanup
13421316
Assert.IsTrue(coordinator.DownloadCompletionTask.IsCompleted,
13431317
"Background task should be completed");
1344-
Assert.IsNotNull(coordinator.DownloadException,
1345-
"Cancellation exception should be captured");
1318+
Assert.IsTrue(coordinator.DownloadCompletionTask.IsFaulted || coordinator.DownloadCompletionTask.IsCanceled,
1319+
"Background task should be faulted or canceled");
13461320
}
13471321

13481322
#endregion
@@ -1424,36 +1398,6 @@ public async Task StartDownloadAsync_SinglePart_WithPreCancelledToken_ThrowsOper
14241398
}
14251399

14261400

1427-
[TestMethod]
1428-
public async Task DiscoverDownloadStrategyAsync_WhenCancelled_SetsDownloadException()
1429-
{
1430-
// Arrange
1431-
var mockClient = new Mock<IAmazonS3>();
1432-
var cancelledException = new OperationCanceledException();
1433-
mockClient.Setup(x => x.GetObjectAsync(It.IsAny<GetObjectRequest>(), It.IsAny<CancellationToken>()))
1434-
.ThrowsAsync(cancelledException);
1435-
1436-
var request = MultipartDownloadTestHelpers.CreateOpenStreamRequest();
1437-
var config = MultipartDownloadTestHelpers.CreateBufferedDownloadConfiguration();
1438-
var coordinator = new MultipartDownloadManager(mockClient.Object, request, config, CreateMockDataHandler().Object);
1439-
1440-
var cts = new CancellationTokenSource();
1441-
cts.Cancel();
1442-
1443-
// Act
1444-
try
1445-
{
1446-
await coordinator.StartDownloadAsync(null, cts.Token);
1447-
}
1448-
catch (OperationCanceledException)
1449-
{
1450-
// Expected
1451-
}
1452-
1453-
// Assert
1454-
Assert.IsNotNull(coordinator.DownloadException);
1455-
Assert.IsInstanceOfType(coordinator.DownloadException, typeof(OperationCanceledException));
1456-
}
14571401

14581402
[TestMethod]
14591403
public async Task DiscoverDownloadStrategyAsync_PassesCancellationTokenToS3Client()
@@ -1549,13 +1493,14 @@ public async Task StartDownloadsAsync_WhenCancelledDuringDownloads_NotifiesBuffe
15491493
// Expected
15501494
}
15511495

1552-
// Assert
1553-
Assert.IsNotNull(coordinator.DownloadException);
1554-
Assert.IsInstanceOfType(coordinator.DownloadException, typeof(OperationCanceledException));
1496+
// Assert - Verify DownloadCompletionTask is faulted with the cancellation exception
1497+
Assert.IsTrue(coordinator.DownloadCompletionTask.IsCompleted, "DownloadCompletionTask should be completed");
1498+
Assert.IsTrue(coordinator.DownloadCompletionTask.IsFaulted || coordinator.DownloadCompletionTask.IsCanceled,
1499+
"DownloadCompletionTask should be faulted or canceled");
15551500
}
15561501

15571502
[TestMethod]
1558-
public async Task StartDownloadsAsync_WhenCancelled_SetsDownloadException()
1503+
public async Task StartDownloadsAsync_WhenCancelled_CompletionTaskIsFaulted()
15591504
{
15601505
// Arrange
15611506
var totalParts = 3;
@@ -1594,9 +1539,10 @@ public async Task StartDownloadsAsync_WhenCancelled_SetsDownloadException()
15941539
// Expected
15951540
}
15961541

1597-
// Assert
1598-
Assert.IsNotNull(coordinator.DownloadException);
1599-
Assert.IsInstanceOfType(coordinator.DownloadException, typeof(OperationCanceledException));
1542+
// Assert - Verify DownloadCompletionTask is faulted with the cancellation
1543+
Assert.IsTrue(coordinator.DownloadCompletionTask.IsCompleted, "DownloadCompletionTask should be completed");
1544+
Assert.IsTrue(coordinator.DownloadCompletionTask.IsFaulted || coordinator.DownloadCompletionTask.IsCanceled,
1545+
"DownloadCompletionTask should be faulted or canceled");
16001546
}
16011547

16021548
[TestMethod]
@@ -1680,8 +1626,9 @@ public async Task StartDownloadsAsync_CancellationPropagatesAcrossConcurrentDown
16801626
// Expected
16811627
}
16821628

1683-
// Assert - Error should be captured
1684-
Assert.IsNotNull(coordinator.DownloadException);
1629+
// Assert - DownloadCompletionTask should be faulted
1630+
Assert.IsTrue(coordinator.DownloadCompletionTask.IsFaulted || coordinator.DownloadCompletionTask.IsCanceled,
1631+
"DownloadCompletionTask should be faulted or canceled when errors occur");
16851632
}
16861633

16871634
[TestMethod]
@@ -3418,10 +3365,8 @@ public async Task StartDownloadsAsync_BackgroundPartFails_CancelsInternalToken()
34183365
Assert.IsTrue(part3SawCancellation,
34193366
"Part 3 should have received cancellation via internalCts.Token (deterministic with TaskCompletionSource)");
34203367

3421-
Assert.IsNotNull(coordinator.DownloadException,
3422-
"Download exception should be captured when background part fails");
3423-
Assert.IsInstanceOfType(coordinator.DownloadException, typeof(InvalidOperationException),
3424-
"Download exception should be the Part 2 failure");
3368+
Assert.IsTrue(coordinator.DownloadCompletionTask.IsFaulted,
3369+
"DownloadCompletionTask should be faulted when background part fails");
34253370
}
34263371

34273372
[TestMethod]
@@ -3484,7 +3429,7 @@ public async Task StartDownloadsAsync_MultiplePartsFail_HandlesGracefully()
34843429

34853430
// Assert - Should handle multiple failures gracefully
34863431
Assert.IsTrue(failedParts.Count > 0, "At least one part should have failed");
3487-
Assert.IsNotNull(coordinator.DownloadException, "Download exception should be captured");
3432+
Assert.IsTrue(coordinator.DownloadCompletionTask.IsFaulted, "DownloadCompletionTask should be faulted");
34883433
}
34893434

34903435
[TestMethod]
@@ -3559,10 +3504,14 @@ public async Task StartDownloadsAsync_CancellationRacesWithDispose_HandlesGracef
35593504
// by checking IsCancellationRequested before calling Cancel()
35603505
Assert.IsFalse(objectDisposedExceptionCaught,
35613506
"ObjectDisposedException should not propagate due to IsCancellationRequested check");
3562-
Assert.IsNotNull(coordinator.DownloadException,
3563-
"Download exception should be the original failure, not ObjectDisposedException");
3564-
Assert.IsInstanceOfType(coordinator.DownloadException, typeof(InvalidOperationException),
3565-
"Download exception should be the original InvalidOperationException from Part 2 failure");
3507+
Assert.IsTrue(coordinator.DownloadCompletionTask.IsFaulted,
3508+
"DownloadCompletionTask should be faulted with the original failure");
3509+
3510+
// Verify the exception type via the Task's exception
3511+
var aggregateException = coordinator.DownloadCompletionTask.Exception;
3512+
Assert.IsNotNull(aggregateException, "Task should have an exception");
3513+
Assert.IsInstanceOfType(aggregateException.InnerException, typeof(InvalidOperationException),
3514+
"Inner exception should be the original InvalidOperationException from Part 2 failure");
35663515
}
35673516

35683517
[TestMethod]
@@ -3640,10 +3589,8 @@ public async Task StartDownloadsAsync_PartFailsDuringDownload_OriginalExceptionP
36403589
Assert.AreEqual("Simulated Part 3 failure", caughtException.Message,
36413590
"The original exception message should be preserved");
36423591

3643-
// Also verify DownloadException matches
3644-
Assert.IsNotNull(coordinator.DownloadException, "DownloadException should be set");
3645-
Assert.IsInstanceOfType(coordinator.DownloadException, typeof(InvalidOperationException),
3646-
"DownloadException should also be InvalidOperationException");
3592+
// Also verify DownloadCompletionTask is faulted
3593+
Assert.IsTrue(coordinator.DownloadCompletionTask.IsFaulted, "DownloadCompletionTask should be faulted");
36473594
}
36483595

36493596
#endregion

0 commit comments

Comments
 (0)