Skip to content

Commit a92a064

Browse files
committed
Add DownloadInitiated, Failed and Completed events
stack-info: PR: #4079, branch: GarrettBeatty/stacked/10
1 parent 6d18ba4 commit a92a064

File tree

6 files changed

+513
-2
lines changed

6 files changed

+513
-2
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"services": [
3+
{
4+
"serviceName": "S3",
5+
"type": "minor",
6+
"changeLogMessages": [
7+
"Added DownloadInitiatedEvent, DownloadCompletedEvent, and DownloadFailedEvent for downloads."
8+
]
9+
}
10+
]
11+
}

sdk/src/Services/S3/Custom/Model/GetObjectResponse.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
using Amazon.S3.Model.Internal.MarshallTransformations;
2626
using Amazon.S3;
2727
using Amazon.Runtime.Internal;
28+
using Amazon.S3.Transfer;
2829

2930
namespace Amazon.S3.Model
3031
{
@@ -1042,5 +1043,10 @@ internal WriteObjectProgressArgs(string bucketName, string key, string filePath,
10421043
/// True if writing is complete
10431044
/// </summary>
10441045
public bool IsCompleted { get; private set; }
1046+
1047+
/// <summary>
1048+
/// The original TransferUtilityDownloadRequest created by the user.
1049+
/// </summary>
1050+
public TransferUtilityDownloadRequest Request { get; internal set; }
10451051
}
10461052
}

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,34 @@ static Logger Logger
6262

6363
IAmazonS3 _s3Client;
6464
TransferUtilityDownloadRequest _request;
65+
long _totalTransferredBytes;
66+
67+
#region Event Firing Methods
68+
69+
private void FireTransferInitiatedEvent()
70+
{
71+
var transferInitiatedEventArgs = new DownloadInitiatedEventArgs(_request, _request.FilePath);
72+
_request.OnRaiseTransferInitiatedEvent(transferInitiatedEventArgs);
73+
}
74+
75+
private void FireTransferCompletedEvent(TransferUtilityDownloadResponse response, string filePath, long transferredBytes, long totalBytes)
76+
{
77+
var transferCompletedEventArgs = new DownloadCompletedEventArgs(
78+
_request,
79+
response,
80+
filePath,
81+
transferredBytes,
82+
totalBytes);
83+
_request.OnRaiseTransferCompletedEvent(transferCompletedEventArgs);
84+
}
85+
86+
private void FireTransferFailedEvent(string filePath, long transferredBytes, long totalBytes = -1)
87+
{
88+
var eventArgs = new DownloadFailedEventArgs(this._request, filePath, transferredBytes, totalBytes);
89+
this._request.OnRaiseTransferFailedEvent(eventArgs);
90+
}
91+
92+
#endregion
6593

6694
internal DownloadCommand(IAmazonS3 s3Client, TransferUtilityDownloadRequest request)
6795
{
@@ -89,6 +117,12 @@ private void ValidateRequest()
89117

90118
void OnWriteObjectProgressEvent(object sender, WriteObjectProgressArgs e)
91119
{
120+
// Keep track of the total transferred bytes so that we can also return this value in case of failure
121+
Interlocked.Add(ref _totalTransferredBytes, e.IncrementTransferred);
122+
123+
// Set the Request property to enable access to the original download request
124+
e.Request = this._request;
125+
92126
this._request.OnRaiseProgressEvent(e);
93127
}
94128

sdk/src/Services/S3/Custom/Transfer/Internal/_async/DownloadCommand.async.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,19 @@ internal partial class DownloadCommand : BaseCommand<TransferUtilityDownloadResp
3333
public override async Task<TransferUtilityDownloadResponse> ExecuteAsync(CancellationToken cancellationToken)
3434
{
3535
ValidateRequest();
36+
37+
FireTransferInitiatedEvent();
38+
3639
GetObjectRequest getRequest = ConvertToGetObjectRequest(this._request);
3740

3841
var maxRetries = _s3Client.Config.MaxErrorRetry;
3942
var retries = 0;
4043
bool shouldRetry = false;
4144
string mostRecentETag = null;
45+
TransferUtilityDownloadResponse lastSuccessfulMappedResponse = null;
46+
long? totalBytesFromResponse = null; // Track total bytes once we have response headers
47+
long totalTransferredBytes = 0;
48+
4249
do
4350
{
4451
shouldRetry = false;
@@ -54,12 +61,16 @@ public override async Task<TransferUtilityDownloadResponse> ExecuteAsync(Cancell
5461
using (var response = await this._s3Client.GetObjectAsync(getRequest, cancellationToken)
5562
.ConfigureAwait(continueOnCapturedContext: false))
5663
{
64+
// Capture total bytes from response headers as soon as we get them
65+
totalBytesFromResponse = response.ContentLength;
66+
5767
if (!string.IsNullOrEmpty(mostRecentETag) && !string.Equals(mostRecentETag, response.ETag))
5868
{
5969
//if the eTag changed, we need to retry from the start of the file
6070
mostRecentETag = response.ETag;
6171
getRequest.ByteRange = null;
6272
retries = 0;
73+
Interlocked.Exchange(ref _totalTransferredBytes, 0);
6374
shouldRetry = true;
6475
WaitBeforeRetry(retries);
6576
continue;
@@ -101,6 +112,9 @@ await response.WriteResponseStreamToFileAsync(this._request.FilePath, false, can
101112
await response.WriteResponseStreamToFileAsync(this._request.FilePath, true, cancellationToken)
102113
.ConfigureAwait(continueOnCapturedContext: false);
103114
}
115+
116+
lastSuccessfulMappedResponse = ResponseMapper.MapGetObjectResponse(response);
117+
totalTransferredBytes = Interlocked.Read(ref _totalTransferredBytes);
104118
}
105119
}
106120
catch (Exception exception)
@@ -109,6 +123,9 @@ await response.WriteResponseStreamToFileAsync(this._request.FilePath, true, canc
109123
shouldRetry = HandleExceptionForHttpClient(exception, retries, maxRetries);
110124
if (!shouldRetry)
111125
{
126+
// Pass total bytes if we have them from response headers, otherwise -1 for unknown
127+
FireTransferFailedEvent(this._request.FilePath, Interlocked.Read(ref _totalTransferredBytes), totalBytesFromResponse ?? -1);
128+
112129
if (exception is IOException)
113130
{
114131
throw;
@@ -131,8 +148,9 @@ await response.WriteResponseStreamToFileAsync(this._request.FilePath, true, canc
131148
WaitBeforeRetry(retries);
132149
} while (shouldRetry);
133150

134-
// TODO map and return response
135-
return new TransferUtilityDownloadResponse();
151+
FireTransferCompletedEvent(lastSuccessfulMappedResponse, this._request.FilePath, totalTransferredBytes, totalBytesFromResponse ?? -1);
152+
153+
return lastSuccessfulMappedResponse;
136154
}
137155

138156
private static bool HandleExceptionForHttpClient(Exception exception, int retries, int maxRetries)

0 commit comments

Comments
 (0)