Skip to content

Commit b773efd

Browse files
authored
Adding detailed failure event handler for DataMovement Tests and fixed Cancellation Exception event being raised unnecessarily (Azure#35441)
* WIP - made failuretransferholder, still need to apply it to the rest of the tests * Updated single download tests * Added FailureTransferHolder to rest of tests * Corrected failure tests to check the error messages instead of asserting failure on expected failures * Remove assert failure check on expected failure tests; Fixed bug where cancellation exception gets event raised * Undo reenabling pause and resume tests * Actually reverting the pause tests to be ignored instead of liveonly
1 parent 1704f1b commit b773efd

18 files changed

+353
-355
lines changed

sdk/storage/Azure.Storage.DataMovement/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## 12.0.0-beta.2 (Unreleased)
44
- Fix to prevent thread starvation on the DataTransfer.AwaitCompletion
5+
- Fix to prevent unnecessary OperationCancelledException's showing up in the SingleTransferOptions.TransferFailed and ContainerTransferOptions.TransferFailed when cancelling a job.
56

67
## 12.0.0-beta.1 (2022-12-15)
78
- This preview is the first release of a ground-up rewrite of our client data movement

sdk/storage/Azure.Storage.DataMovement/src/CommitChunkHandler.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,6 @@ await _invokeFailedEventHandler(
182182
_currentBytesSemaphore.Release();
183183
}
184184
}
185-
catch (OperationCanceledException)
186-
{
187-
// If operation cancelled, no need to log the exception. As it's logged by whoever called the cancellation (e.g. disposal)
188-
}
189185
catch (Exception ex)
190186
{
191187
await _invokeFailedEventHandler(ex).ConfigureAwait(false);

sdk/storage/Azure.Storage.DataMovement/src/DownloadChunkHandler.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,6 @@ await InvokeFailedEvent(
254254
_currentBytesSemaphore.Release();
255255
}
256256
}
257-
catch (OperationCanceledException)
258-
{
259-
// If operation cancelled, no need to log the exception. As it's logged by whoever called the cancellation (e.g. disposal)
260-
}
261257
catch (Exception ex)
262258
{
263259
await _invokeFailedEventHandler(ex).ConfigureAwait(false);

sdk/storage/Azure.Storage.DataMovement/src/JobPartInternal.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,8 @@ await TransferSkippedEventHandler.Invoke(new TransferSkippedEventArgs(
334334
/// </summary>
335335
public async virtual Task InvokeFailedArg(Exception ex)
336336
{
337-
if (TransferFailedEventHandler != null)
337+
if (TransferFailedEventHandler != null &&
338+
ex is not OperationCanceledException)
338339
{
339340
// TODO: change to RaiseAsync
340341
await TransferFailedEventHandler.Invoke(new TransferFailedEventArgs(

sdk/storage/Azure.Storage.DataMovement/src/ServiceToServiceJobPart.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -424,13 +424,6 @@ await _commitBlockHandler.InvokeEvent(
424424
true,
425425
_cancellationToken)).ConfigureAwait(false);
426426
}
427-
// If we fail to stage a block, we need to make sure the rest of the stage blocks are cancelled
428-
// (Core already performs the retry policy on the one stage block request
429-
// which means the rest are not worth to continue)
430-
catch (OperationCanceledException)
431-
{
432-
// Job was cancelled
433-
}
434427
catch (RequestFailedException ex)
435428
when (_createMode == StorageResourceCreateMode.Overwrite
436429
&& ex.ErrorCode == "BlobAlreadyExists")

sdk/storage/Azure.Storage.DataMovement/src/StreamToUriJobPart.cs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,6 @@ await _destinationResource.WriteFromStreamAsync(
268268
{
269269
await InvokeSkippedArg().ConfigureAwait(false);
270270
}
271-
catch (OperationCanceledException)
272-
{
273-
// expected exception during job part cancellation or pause.
274-
}
275271
catch (Exception ex)
276272
{
277273
await InvokeFailedArg(ex).ConfigureAwait(false);
@@ -343,13 +339,6 @@ await _commitBlockHandler.InvokeEvent(
343339
true,
344340
_cancellationToken)).ConfigureAwait(false);
345341
}
346-
// If we fail to stage a block, we need to make sure the rest of the stage blocks are cancelled
347-
// (Core already performs the retry policy on the one stage block request
348-
// which means the rest are not worth to continue)
349-
catch (OperationCanceledException)
350-
{
351-
// Job was cancelled
352-
}
353342
catch (Exception ex)
354343
{
355344
await InvokeFailedArg(ex).ConfigureAwait(false);

sdk/storage/Azure.Storage.DataMovement/src/UriToStreamJobPart.cs

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,6 @@ public override async Task ProcessPartToChunkAsync()
145145
await LengthKnownDownloadInternal().ConfigureAwait(false);
146146
}
147147
}
148-
catch (OperationCanceledException)
149-
{
150-
// Job was cancelled
151-
await OnTransferStatusChanged(StorageTransferStatus.None).ConfigureAwait(false);
152-
}
153148
catch (Exception ex)
154149
{
155150
// The file either does not exist any more, got moved, or renamed.
@@ -342,11 +337,6 @@ await _downloadChunkHandler.InvokeEvent(new DownloadRangeEventArgs(
342337
false,
343338
_cancellationToken)).ConfigureAwait(false);
344339
}
345-
catch (OperationCanceledException)
346-
{
347-
// Job was cancelled
348-
await OnTransferStatusChanged(StorageTransferStatus.None).ConfigureAwait(false);
349-
}
350340
catch (Exception ex)
351341
{
352342
// Unexpected exception
@@ -382,11 +372,6 @@ await _destinationResource.WriteFromStreamAsync(
382372
// Skip file that already exsits on the destination.
383373
await InvokeSkippedArg().ConfigureAwait(false);
384374
}
385-
catch (OperationCanceledException)
386-
{
387-
// Job was cancelled
388-
await OnTransferStatusChanged(StorageTransferStatus.None).ConfigureAwait(false);
389-
}
390375
catch (Exception ex)
391376
{
392377
await InvokeFailedArg(ex).ConfigureAwait(false);
@@ -409,11 +394,6 @@ await source.CopyToAsync(
409394
.ConfigureAwait(false);
410395
}
411396
}
412-
catch (OperationCanceledException)
413-
{
414-
// Job was cancelled
415-
await OnTransferStatusChanged(StorageTransferStatus.None).ConfigureAwait(false);
416-
}
417397
catch (Exception ex)
418398
{
419399
await InvokeFailedArg(ex).ConfigureAwait(false);
@@ -430,11 +410,6 @@ private async Task FlushFinalCryptoStreamInternal()
430410
{
431411
await _destinationResource.CompleteTransferAsync(_cancellationToken).ConfigureAwait(false);
432412
}
433-
catch (OperationCanceledException)
434-
{
435-
// Job was cancelled
436-
await OnTransferStatusChanged(StorageTransferStatus.None).ConfigureAwait(false);
437-
}
438413
catch (Exception ex)
439414
{
440415
await InvokeFailedArg(ex).ConfigureAwait(false);

sdk/storage/Azure.Storage.DataMovement/tests/FailureTrackingTransfer.cs

Lines changed: 0 additions & 53 deletions
This file was deleted.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System.Collections.Generic;
5+
using System.Threading.Tasks;
6+
using Azure.Storage.DataMovement.Models;
7+
using NUnit.Framework;
8+
9+
namespace Azure.Storage.DataMovement.Tests
10+
{
11+
/// <summary>
12+
/// Stores the option bag and failures as the test progresses.
13+
///
14+
/// This prevents a test from being torn down terribly when doing
15+
/// an Assert.Failure in the middle of an event.
16+
///
17+
/// Alos if there's multiple failures then we will catch all of them.
18+
/// (Which would mainly occur during <see cref="ErrorHandlingOptions.ContinueOnFailure"/>
19+
/// </summary>
20+
internal class FailureTransferHolder
21+
{
22+
public List<TransferFailedEventArgs> FailedEvents { get; internal set; }
23+
24+
private FailureTransferHolder()
25+
{
26+
FailedEvents = new List<TransferFailedEventArgs>();
27+
}
28+
29+
public FailureTransferHolder(ContainerTransferOptions options)
30+
: this()
31+
{
32+
options.TransferFailed += AppendFailedArg;
33+
}
34+
35+
public FailureTransferHolder(SingleTransferOptions options)
36+
: this()
37+
{
38+
options.TransferFailed += AppendFailedArg;
39+
}
40+
41+
public FailureTransferHolder(List<SingleTransferOptions> optionsList)
42+
: this()
43+
{
44+
foreach (SingleTransferOptions options in optionsList)
45+
{
46+
options.TransferFailed += AppendFailedArg;
47+
}
48+
}
49+
public FailureTransferHolder(List<ContainerTransferOptions> optionsList)
50+
: this()
51+
{
52+
foreach (ContainerTransferOptions options in optionsList)
53+
{
54+
options.TransferFailed += AppendFailedArg;
55+
}
56+
}
57+
58+
private Task AppendFailedArg(TransferFailedEventArgs args)
59+
{
60+
FailedEvents.Add(args);
61+
return Task.CompletedTask;
62+
}
63+
64+
public void AssertFailureCheck()
65+
{
66+
Assert.Multiple(() =>
67+
{
68+
foreach (TransferFailedEventArgs failure in FailedEvents)
69+
{
70+
Assert.Fail(
71+
$"Failure occurred at Transfer id: {failure.TransferId}.\n" +
72+
$"Source Resource Path: {failure.SourceResource.Path}\n" +
73+
$"Destination Resource Path: {failure.DestinationResource.Path}\n" +
74+
$"Exception Message: {failure.Exception.Message}\n" +
75+
$"Exception Stack: {failure.Exception.StackTrace}\n");
76+
}
77+
});
78+
}
79+
}
80+
}

0 commit comments

Comments
 (0)