diff --git a/source/settlement-report/SettlementReports.Application/Handlers/ListSettlementReportJobsHandler.cs b/source/settlement-report/SettlementReports.Application/Handlers/ListSettlementReportJobsHandler.cs index f21a1dc..40f96d6 100644 --- a/source/settlement-report/SettlementReports.Application/Handlers/ListSettlementReportJobsHandler.cs +++ b/source/settlement-report/SettlementReports.Application/Handlers/ListSettlementReportJobsHandler.cs @@ -12,9 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +using Energinet.DataHub.SettlementReport.Application.SettlementReports_v2; using Energinet.DataHub.SettlementReport.Interfaces.Helpers; using Energinet.DataHub.SettlementReport.Interfaces.SettlementReports_v2; using Energinet.DataHub.SettlementReport.Interfaces.SettlementReports_v2.Models; +using NodaTime; namespace Energinet.DataHub.SettlementReport.Application.Handlers; @@ -22,13 +24,19 @@ public sealed class ListSettlementReportJobsHandler : IListSettlementReportJobsH { private readonly IDatabricksJobsHelper _jobHelper; private readonly IGetSettlementReportsHandler _getSettlementReportsHandler; + private readonly ISettlementReportRepository _repository; + private readonly IClock _clock; public ListSettlementReportJobsHandler( IDatabricksJobsHelper jobHelper, - IGetSettlementReportsHandler getSettlementReportsHandler) + IGetSettlementReportsHandler getSettlementReportsHandler, + ISettlementReportRepository repository, + IClock clock) { _jobHelper = jobHelper; _getSettlementReportsHandler = getSettlementReportsHandler; + _repository = repository; + _clock = clock; } public async Task> HandleAsync() @@ -36,18 +44,39 @@ public async Task> HandleAsync() var settlementReports = (await _getSettlementReportsHandler .GetAsync() .ConfigureAwait(false)) - .Where(x => x.JobId is not null).ToList(); + .Where(x => x.JobId is not null && x.Status != SettlementReportStatus.Completed).ToList(); var results = new List(); foreach (var settlementReportDto in settlementReports) { var jobStatus = await _jobHelper.GetSettlementReportsJobStatusAsync(settlementReportDto.JobId!.Id).ConfigureAwait(false); + if (jobStatus == JobRunStatus.Completed) + { + await MarkAsCompletedAsync(settlementReportDto).ConfigureAwait(false); + } + results.Add(settlementReportDto with { Status = MapFromJobStatus(jobStatus) }); } return results; } + private async Task MarkAsCompletedAsync(RequestedSettlementReportDto settlementReportDto) + { + ArgumentNullException.ThrowIfNull(settlementReportDto); + ArgumentNullException.ThrowIfNull(settlementReportDto.JobId); + + var request = await _repository + .GetAsync(settlementReportDto.JobId.Id) + .ConfigureAwait(false); + + request.MarkAsCompleted(_clock, settlementReportDto.JobId); + + await _repository + .AddOrUpdateAsync(request) + .ConfigureAwait(false); + } + private SettlementReportStatus MapFromJobStatus(JobRunStatus status) { return status switch diff --git a/source/settlement-report/SettlementReports.Application/SettlementReports_v2/ISettlementReportJobsFileRepository.cs b/source/settlement-report/SettlementReports.Application/SettlementReports_v2/ISettlementReportJobsFileRepository.cs new file mode 100644 index 0000000..d604c2b --- /dev/null +++ b/source/settlement-report/SettlementReports.Application/SettlementReports_v2/ISettlementReportJobsFileRepository.cs @@ -0,0 +1,22 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Energinet.DataHub.SettlementReport.Interfaces.SettlementReports_v2.Models; + +namespace Energinet.DataHub.SettlementReport.Application.SettlementReports_v2; + +public interface ISettlementReportJobsFileRepository +{ + Task DownloadAsync(JobRunId jobRunId, string fileName, Stream downloadStream); +} diff --git a/source/settlement-report/SettlementReports.Application/SettlementReports_v2/SettlementReport.cs b/source/settlement-report/SettlementReports.Application/SettlementReports_v2/SettlementReport.cs index 8fa8a89..828ff88 100644 --- a/source/settlement-report/SettlementReports.Application/SettlementReports_v2/SettlementReport.cs +++ b/source/settlement-report/SettlementReports.Application/SettlementReports_v2/SettlementReport.cs @@ -106,6 +106,13 @@ public void MarkAsCompleted(IClock clock, GeneratedSettlementReportDto generated EndedDateTime = clock.GetCurrentInstant(); } + public void MarkAsCompleted(IClock clock, JobRunId jobRunId) + { + Status = SettlementReportStatus.Completed; + BlobFileName = jobRunId.Id.ToString(); + EndedDateTime = clock.GetCurrentInstant(); + } + public void MarkAsFailed() { Status = SettlementReportStatus.Failed; diff --git a/source/settlement-report/SettlementReports.Infrastructure/Extensions/DependencyInjection/StorageExtensions.cs b/source/settlement-report/SettlementReports.Infrastructure/Extensions/DependencyInjection/StorageExtensions.cs index 6e1e900..9831469 100644 --- a/source/settlement-report/SettlementReports.Infrastructure/Extensions/DependencyInjection/StorageExtensions.cs +++ b/source/settlement-report/SettlementReports.Infrastructure/Extensions/DependencyInjection/StorageExtensions.cs @@ -52,8 +52,43 @@ public static IServiceCollection AddSettlementReportBlobStorage(this IServiceCol { var blobSettings = serviceProvider.GetRequiredService>().Value; options.ContainerName = blobSettings.StorageContainerName; + }, + "SettlementReportBlobStorage"); + + return services; + } + + public static IServiceCollection AddSettlementReportBlobStorageForJobs(this IServiceCollection services) + { + services + .AddOptions() + .BindConfiguration(SettlementReportStorageOptions.SectionName) + .ValidateDataAnnotations(); + + services.AddScoped(serviceProvider => + { + var blobSettings = serviceProvider.GetRequiredService>().Value; + + var blobContainerUri = new Uri(blobSettings.StorageAccountJobsUri, blobSettings.StorageContainerJobsName); + var blobContainerClient = new BlobContainerClient(blobContainerUri, new DefaultAzureCredential()); + + return new SettlementReportJobsFileBlobStorage(blobContainerClient); }); + // Health checks + services.AddHealthChecks().AddAzureBlobStorage( + serviceProvider => + { + var blobSettings = serviceProvider.GetRequiredService>().Value; + return new BlobServiceClient(blobSettings.StorageAccountUri, new DefaultAzureCredential()); + }, + (serviceProvider, options) => + { + var blobSettings = serviceProvider.GetRequiredService>().Value; + options.ContainerName = blobSettings.StorageContainerName; + }, + "SettlementReportBlobStorage - Jobs"); + return services; } } diff --git a/source/settlement-report/SettlementReports.Infrastructure/Extensions/Options/SettlementReportStorageOptions.cs b/source/settlement-report/SettlementReports.Infrastructure/Extensions/Options/SettlementReportStorageOptions.cs index fa83d67..8486ed5 100644 --- a/source/settlement-report/SettlementReports.Infrastructure/Extensions/Options/SettlementReportStorageOptions.cs +++ b/source/settlement-report/SettlementReports.Infrastructure/Extensions/Options/SettlementReportStorageOptions.cs @@ -25,4 +25,10 @@ public class SettlementReportStorageOptions [Required] public string StorageContainerName { get; set; } = string.Empty; + + [Required] + public Uri StorageAccountJobsUri { get; set; } = null!; + + [Required] + public string StorageContainerJobsName { get; set; } = string.Empty; } diff --git a/source/settlement-report/SettlementReports.Infrastructure/SettlementReports_v2/SettlementReportJobsFileBlobStorage.cs b/source/settlement-report/SettlementReports.Infrastructure/SettlementReports_v2/SettlementReportJobsFileBlobStorage.cs new file mode 100644 index 0000000..52c2ae7 --- /dev/null +++ b/source/settlement-report/SettlementReports.Infrastructure/SettlementReports_v2/SettlementReportJobsFileBlobStorage.cs @@ -0,0 +1,41 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Azure.Storage.Blobs; +using Energinet.DataHub.SettlementReport.Application.SettlementReports_v2; +using Energinet.DataHub.SettlementReport.Interfaces.SettlementReports_v2.Models; + +namespace Energinet.DataHub.SettlementReport.Infrastructure.SettlementReports_v2; + +public sealed class SettlementReportJobsFileBlobStorage : ISettlementReportJobsFileRepository +{ + private readonly BlobContainerClient _blobContainerClient; + + public SettlementReportJobsFileBlobStorage(BlobContainerClient blobContainerClient) + { + _blobContainerClient = blobContainerClient; + } + + public async Task DownloadAsync(JobRunId jobRunId, string fileName, Stream downloadStream) + { + var blobName = GetBlobName(jobRunId, fileName); + var blobClient = _blobContainerClient.GetBlobClient(blobName); + await blobClient.DownloadToAsync(downloadStream).ConfigureAwait(false); + } + + private static string GetBlobName(JobRunId jobRunId, string fileName) + { + return string.Join('/', "settlement-reports", jobRunId.Id, fileName); + } +}