Skip to content

Commit 2fb1459

Browse files
committed
Add DownloadInitiated, Failed and Completed events
stack-info: PR: #4079, branch: GarrettBeatty/stacked/10
1 parent 60fdeae commit 2fb1459

File tree

6 files changed

+502
-2
lines changed

6 files changed

+502
-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: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,17 @@ 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
4247
do
4348
{
4449
shouldRetry = false;
@@ -54,12 +59,16 @@ public override async Task<TransferUtilityDownloadResponse> ExecuteAsync(Cancell
5459
using (var response = await this._s3Client.GetObjectAsync(getRequest, cancellationToken)
5560
.ConfigureAwait(continueOnCapturedContext: false))
5661
{
62+
// Capture total bytes from response headers as soon as we get them
63+
totalBytesFromResponse = response.ContentLength;
64+
5765
if (!string.IsNullOrEmpty(mostRecentETag) && !string.Equals(mostRecentETag, response.ETag))
5866
{
5967
//if the eTag changed, we need to retry from the start of the file
6068
mostRecentETag = response.ETag;
6169
getRequest.ByteRange = null;
6270
retries = 0;
71+
Interlocked.Exchange(ref _totalTransferredBytes, 0);
6372
shouldRetry = true;
6473
WaitBeforeRetry(retries);
6574
continue;
@@ -101,6 +110,8 @@ await response.WriteResponseStreamToFileAsync(this._request.FilePath, false, can
101110
await response.WriteResponseStreamToFileAsync(this._request.FilePath, true, cancellationToken)
102111
.ConfigureAwait(continueOnCapturedContext: false);
103112
}
113+
114+
lastSuccessfulMappedResponse = ResponseMapper.MapGetObjectResponse(response);
104115
}
105116
}
106117
catch (Exception exception)
@@ -109,6 +120,9 @@ await response.WriteResponseStreamToFileAsync(this._request.FilePath, true, canc
109120
shouldRetry = HandleExceptionForHttpClient(exception, retries, maxRetries);
110121
if (!shouldRetry)
111122
{
123+
// Pass total bytes if we have them from response headers, otherwise -1 for unknown
124+
FireTransferFailedEvent(this._request.FilePath, Interlocked.Read(ref _totalTransferredBytes), totalBytesFromResponse ?? -1);
125+
112126
if (exception is IOException)
113127
{
114128
throw;
@@ -131,8 +145,9 @@ await response.WriteResponseStreamToFileAsync(this._request.FilePath, true, canc
131145
WaitBeforeRetry(retries);
132146
} while (shouldRetry);
133147

134-
// TODO map and return response
135-
return new TransferUtilityDownloadResponse();
148+
FireTransferCompletedEvent(lastSuccessfulMappedResponse, this._request.FilePath, Interlocked.Read(ref _totalTransferredBytes), totalBytesFromResponse ?? -1);
149+
150+
return lastSuccessfulMappedResponse;
136151
}
137152

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

0 commit comments

Comments
 (0)