using System; using System.Text; using System.Linq; using System.Collections.Generic; using Serilog; using Newtonsoft.Json; using LCU.Library.Internal.ApiResponse.Models; using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; using LCU.Library.Internal.FileOperationsModels.Models; using LCU.Api.Internal.ArchiverApi.Configuration; using LCU.Api.Internal.MaidBotLib.Models; using LCU.Library.Internal.ApiResponse.Services; using LCU.Library.Internal.ArchiverApiModel.Models; using LCU.Library.Internal.LcuMassTransitModels; namespace LCU.Api.Internal.ArchiverApi.Services; public class ArchiverService : IArchiverService { private readonly ArchiverApiConfig _ArchiverApiConfig; private readonly IReportService _reportService; private readonly IFileOperationsService _fileOperationsService; private readonly ConnectionConfiguration _connectionConfiguration; private readonly ReceiveEndpointConfiguration _receiveEndpointsConfiguration; private const string NameRegexStartTag = "{Regex0}"; private const string NameRegexStart = "^(" + RegexStartCaseInsenstive; private const string NameRegexEndTag = "{Regex1}"; private const string NameRegexEnd = RegexStopCaseInsenstive + ")"; private const string AnyWordAndPeriodRegexTag = "{Regex2}"; private const string AnyWordAndPeriodRegex = "\\w*\\."; private const string ExtensionRegexTag = "{Regex3}"; private const string ExtensionRegexStart = "("; private const string ExtensionRegexEnd = ")$"; private const string RegexPipe = "|"; private const string RegexStartCaseInsenstive = "(?i)"; private const string RegexStopCaseInsenstive = "(?-i)"; public ArchiverService(ArchiverApiConfig ArchiverApiConfig, IReportService reportService, IFileOperationsService fileOperationsService, ConnectionConfiguration connectionConfiguration, ReceiveEndpointConfigurations receiveEndpointsConfiguration) { _ArchiverApiConfig = ArchiverApiConfig; _reportService = reportService; _fileOperationsService = fileOperationsService; _connectionConfiguration = connectionConfiguration; _receiveEndpointsConfiguration = receiveEndpointsConfiguration.ResponseReceiveEndpoint; } public void ExecuteRequest(ArchiveRequest archiveRequest) { try { var archiveResult = HandleArchiveRequest(archiveRequest); if (!archiveResult.archiveRequestResponse.IsSuccessful) { var errorMessage = String.Join("; ", archiveResult.archiveRequestResponse.MessageStack.ToArray()); Log.Error($"Archive Request was not successful. MessaggeStack:{errorMessage}"); } //Happy path we queue return response later in ArchivecompletionService after the BulkOperations has been preformed. if (archiveResult.queueReturnResponse) { QueueReturnResponse.QueueResponse(archiveRequest, archiveResult.archiveRequestResponse.IsSuccessful, archiveResult.archiveRequestResponse.MessageStack); } } catch (Exception exception) { Log.ForContext(nameof(PropertyEnum.Group), nameof(GroupEnum.ITDevelopment)) .Error(exception, $"Error while archiving reports. Look into failed ArchiveRequest. " + $"ArchiveRequest: {JsonConvert.SerializeObject(archiveRequest)}"); } } public (ArchiveRequestResponse archiveRequestResponse, bool queueReturnResponse) HandleArchiveRequest(ArchiveRequest archiveRequest) { var archiveRequestResponse = new ArchiveRequestResponse(); try { var reports = _reportService.GetReportsToArchiveAsync(archiveRequest).Result; if (!reports.Any()) { Log.Information("No reports to bulk move."); archiveRequestResponse.MessageStack.Add("No application histories retrieved from DNA database to move."); archiveRequestResponse.IsSuccessful = archiveRequest.SucceedIfEmpty; return (archiveRequestResponse, true); } var bulkOperationRequest = BuildBulkOperationRequest(reports, archiveRequest); if (!bulkOperationRequest.OperationRequests.Any()) { Log.Information("There are no files to bulk move."); archiveRequestResponse.MessageStack.Add("There are no files to bulk move."); archiveRequestResponse.IsSuccessful = archiveRequest.SucceedIfEmpty; return (archiveRequestResponse, true); } bulkOperationRequest = SetUpResponse(bulkOperationRequest, archiveRequest, archiveRequestResponse); _fileOperationsService.SendBulkOperationsAsync(bulkOperationRequest); } catch (Exception exception) { archiveRequestResponse.IsSuccessful = false; var anyIdentifiers = archiveRequest.ArchiveIdentifiers != null && archiveRequest.ArchiveIdentifiers.Any(); var identifiers = anyIdentifiers ? String.Join(", ", archiveRequest.ArchiveIdentifiers.ToArray()) : ""; archiveRequestResponse.MessageStack.Add($"Failure to execute archive request. " + $"EffectiveDate: [{archiveRequest.EffectiveDate}], " + $"DaysFromDate: [{archiveRequest.DaysFromDate}], " + $"ArchiveDestinationBase: [{archiveRequest.ArchiveDestinationBase}], " + $"Identifiers: [{identifiers}], " + $"Exception: {exception} "); } return (archiveRequestResponse, !archiveRequestResponse.IsSuccessful); } public BulkOperationRequest BuildBulkOperationRequest(IEnumerable reports, ArchiveRequest archiveRequest) { try { var bulkOperationRequest = new BulkOperationRequest(); bulkOperationRequest.OperationRequests = new List(); var extensionRegex = new RegexSetting() { Tag = ExtensionRegexTag, Regex = BuildExtensionRegexString(archiveRequest) }; var anyWordAndPeriodRegex = new RegexSetting() { Tag = AnyWordAndPeriodRegexTag, Regex = AnyWordAndPeriodRegex }; foreach (var report in reports) { var nameSettings = SetUpNameSettings(report); nameSettings.RegexSettings.Add(anyWordAndPeriodRegex); nameSettings.RegexSettings.Add(extensionRegex); var dynamicallyNamedRequests = CreateOperationRequests(report, nameSettings, archiveRequest); bulkOperationRequest.OperationRequests.AddRange(dynamicallyNamedRequests); } return bulkOperationRequest; } catch (AggregateException exception) { throw new AggregateException($"Error while attempting to build bulk operation request. " + $"Exception Message: {exception.Message}"); } catch (Exception exception) { throw new Exception($"Error while attempting to build bulk operation request. " + $"Exception Message: {exception.Message}"); } } public string BuildExtensionRegexString(ArchiveRequest archiveRequest) { var regexStringBuilder = new StringBuilder(); regexStringBuilder.Append(ExtensionRegexStart); for (int index = 0; index < archiveRequest.AllowedExensions.Count; ++index) { var pipe = index == archiveRequest.AllowedExensions.Count ? "" : RegexPipe; regexStringBuilder.Append(RegexStartCaseInsenstive + archiveRequest.AllowedExensions[index] + RegexStopCaseInsenstive + pipe); } regexStringBuilder.Append(ExtensionRegexEnd); return regexStringBuilder.ToString(); } public List CreateOperationRequests(Report report, DynamicNameSetting nameSettings, ArchiveRequest archiveRequest) { var fileName = report.HasRegexMapping ? report.DisplayReportName : report.FinalReportName; DateTime effectiveDate = archiveRequest.EffectiveDate == null ? DateTime.MinValue : (DateTime)archiveRequest.EffectiveDate; var reportPath = $"{_ArchiverApiConfig.DnaBasePath}\\" + $"{effectiveDate.ToString(_ArchiverApiConfig.ReportPathDateFormat)}\\" + $"{report.QueueNumber}"; var sourceFile = $"{NameRegexStartTag}{fileName}{NameRegexEndTag}{AnyWordAndPeriodRegexTag}{ExtensionRegexTag}"; var files = _fileOperationsService.BuildDynamicFileListAsync(reportPath, sourceFile, nameSettings).Result; var dynamicallyNamedRequests = new List(); foreach (var file in files) { var request = new MoveFileRequest() { SourcePath = reportPath, SourceFile = file, DestinationPath = archiveRequest.ArchiveDestinationBase, FileNameSetting = nameSettings }; SetDestinationName(report, request, archiveRequest); dynamicallyNamedRequests.Add(request); } return dynamicallyNamedRequests; } public void SetDestinationName(Report report, MoveFileRequest request, ArchiveRequest archiveRequest) { var extention = archiveRequest.AllowedExensions .FirstOrDefault(fe => request.SourceFile.Contains($".{fe}", StringComparison.OrdinalIgnoreCase)); if (extention != null) { request.DestinationName = report.BuildDestinationName(request.FinalSourceFile, extention); } } public DynamicNameSetting SetUpNameSettings(Report report) { var nameSettings = new DynamicNameSetting(); nameSettings.RegexSettings = new List() { new RegexSetting() { Tag = NameRegexStartTag, Regex = NameRegexStart }, new RegexSetting() { Tag = NameRegexEndTag, Regex = NameRegexEnd } }; if (report.ApplicationMapping == null) { return nameSettings; }; foreach (var regex in report.ApplicationMapping.RegexMappings) { nameSettings.RegexSettings.Add(new RegexSetting() { Tag = regex.Tag, Regex = regex.Regex, }); } return nameSettings; } public BulkOperationRequest SetUpResponse(BulkOperationRequest bulkOperationRequest, ArchiveRequest archiveRequest, ArchiveRequestResponse archiveRequestResponse) { var archiveResponsePayload = new ArchiveResponsePayload() { ArchiveRequest = archiveRequest, BulkOperationRequest = bulkOperationRequest, ArchiveRequestResponse = archiveRequestResponse }; var responseItem = new ResponseItem { ReturnQueueConsumerConfig = new QueueConsumerConfig() { ExchangeName = _receiveEndpointsConfiguration.ReceiveEndpoint }, ReturnQueueConnectionConfig = new QueueConnectionConfig() { Url = _connectionConfiguration.HostUrl, Username = _connectionConfiguration.UserName, Password = _connectionConfiguration.Password }, ResponsePayload = JsonConvert.SerializeObject(archiveResponsePayload) }; bulkOperationRequest.ResponseItems = new List() { responseItem }; return bulkOperationRequest; } }