Skip to content

Commit c9c65e3

Browse files
authored
LNK-4366: Submission Service: Pass Query Parameter to Endpoint, Default to Internal ABS (#1243)
Support download from both blob containers By default, download from internal (since submissions will be removed from external after downstream ingestion). But for smoke testing, download from external to test full end-to-end flow.
1 parent f6007c0 commit c9c65e3

4 files changed

Lines changed: 35 additions & 14 deletions

File tree

DotNet/Submission/Application/Services/BlobStorageService.cs

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -130,19 +130,13 @@ public async Task UploadToExternalAsync(
130130
await stream.WriteAsync(content, cancellationToken);
131131
}
132132

133-
public async Task<IDictionary<string, byte[]>> DownloadFromExternalAsync(string payloadRootUri, CancellationToken cancellationToken = default)
133+
private async Task<IDictionary<string, byte[]>> DownloadAsync(BlobContainerClient containerClient, string prefix, CancellationToken cancellationToken = default)
134134
{
135-
if (!HasExternalClient())
136-
{
137-
throw new InvalidOperationException("Not configured for external blob storage.");
138-
}
139135
IDictionary<string, byte[]> files = new Dictionary<string, byte[]>();
140-
BlobUriBuilder uriBuilder = new(new Uri(payloadRootUri));
141-
string prefix = ChangeBlobRoot(uriBuilder.BlobName);
142-
await foreach (BlobItem blob in _externalContainerClient.GetBlobsAsync(prefix: prefix, cancellationToken: cancellationToken))
136+
await foreach (BlobItem blob in containerClient.GetBlobsAsync(prefix: prefix, cancellationToken: cancellationToken))
143137
{
144138
_logger.LogDebug("Downloading: {}", blob.Name);
145-
BlockBlobClient blobClient = _externalContainerClient.GetBlockBlobClient(blob.Name);
139+
BlockBlobClient blobClient = containerClient.GetBlockBlobClient(blob.Name);
146140
using Stream input = await blobClient.OpenReadAsync(cancellationToken: cancellationToken);
147141
using MemoryStream output = new();
148142
await input.CopyToAsync(output, cancellationToken);
@@ -152,5 +146,27 @@ public async Task<IDictionary<string, byte[]>> DownloadFromExternalAsync(string
152146
}
153147
return files;
154148
}
149+
150+
public Task<IDictionary<string, byte[]>> DownloadFromInternalAsync(string payloadRootUri, CancellationToken cancellationToken = default)
151+
{
152+
if (!HasInternalClient())
153+
{
154+
throw new InvalidOperationException("Not configured for internal blob storage.");
155+
}
156+
BlobUriBuilder uriBuilder = new(new Uri(payloadRootUri));
157+
string prefix = uriBuilder.BlobName;
158+
return DownloadAsync(_internalContainerClient, prefix, cancellationToken);
159+
}
160+
161+
public Task<IDictionary<string, byte[]>> DownloadFromExternalAsync(string payloadRootUri, CancellationToken cancellationToken = default)
162+
{
163+
if (!HasExternalClient())
164+
{
165+
throw new InvalidOperationException("Not configured for external blob storage.");
166+
}
167+
BlobUriBuilder uriBuilder = new(new Uri(payloadRootUri));
168+
string prefix = ChangeBlobRoot(uriBuilder.BlobName);
169+
return DownloadAsync(_externalContainerClient, prefix, cancellationToken);
170+
}
155171
}
156172
}

DotNet/Submission/Controllers/SubmissionController.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,14 @@ public class SubmissionController(
3030
* Downloads the specified report's data as a ZIP archive
3131
* <param name="facilityId">The ID of the facility</param>
3232
* <param name="reportId">The ID of the report to download</param>
33+
* <param name="external">Whether to download from external or internal (default) storage</param>
3334
* <remarks>Gets information about the report from the report service in order to construct the directory/path for the report.</remarks>
3435
*/
3536
[HttpGet("{facilityId}/{reportId}")]
36-
public async Task<IActionResult> DownloadReport([FromRoute] string facilityId, [FromRoute] string reportId)
37+
public async Task<IActionResult> DownloadReport(
38+
[FromRoute] string facilityId,
39+
[FromRoute] string reportId,
40+
[FromQuery] bool external = false)
3741
{
3842
string sanitizedFacilityId = facilityId.SanitizeAndRemove();
3943

@@ -86,9 +90,10 @@ public async Task<IActionResult> DownloadReport([FromRoute] string facilityId, [
8690
throw new Exception("Missing 'payloadRootUri' in the response.");
8791
}
8892

89-
IDictionary<string, byte[]> files = await blobStorageService.DownloadFromExternalAsync(payloadRootUri.GetString());
93+
IDictionary<string, byte[]> files = external
94+
? await blobStorageService.DownloadFromExternalAsync(payloadRootUri.GetString())
95+
: await blobStorageService.DownloadFromInternalAsync(payloadRootUri.GetString());
9096

91-
// TODO: Consider changing this to store the ZIP on disk, instead, and check if the ZIP already exists
9297
var compressedData = this.CompressFiles(files);
9398

9499
return File(compressedData, "application/zip", $"{sanitizedReportId}.zip");

Tests/BackendE2ETests/AdhocReportingSmokeTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ private async Task GenerateReport(string? measureId)
196196
}
197197
private async Task<Dictionary<string, Object>> DownloadReport(string reportId)
198198
{
199-
var request = new RestRequest($"submission/{FacilityId}/{reportId}", Method.Get);
199+
var request = new RestRequest($"submission/{FacilityId}/{reportId}?external=true", Method.Get);
200200
var response = await AdminBffClient.ExecuteAsync(request);
201201
Assert.True(response.StatusCode == System.Net.HttpStatusCode.OK, $"Download Report - Expected HTTP 200 OK but received {response.StatusCode}: {response.Content}");
202202

Tests/BackendE2ETests/ApiRequests/AdHocReportApiRequests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1022,7 +1022,7 @@ public void GETSingleMeasureAdHocSubmissionDownloadReport()
10221022
};
10231023

10241024
var client = new RestClient(options);
1025-
var request = new RestRequest($"/Submission/{TestConfig.SingleMeasureAdHocFacility}/{AdHocReportGuid}", Method.Get);
1025+
var request = new RestRequest($"/Submission/{TestConfig.SingleMeasureAdHocFacility}/{AdHocReportGuid}?external=true", Method.Get);
10261026
RestResponse response = client.ExecuteAsync(request).GetAwaiter().GetResult();
10271027
WaitForRequestComplete();
10281028
JObject jsonResponse = JObject.Parse(response.Content);

0 commit comments

Comments
 (0)