/// <summary> /// The Method to do what the User decieded /// </summary> /// <param name="data">The Data payload passed by the User</param> /// <param name="activityResultID">The Result ID Passed by the User to indicate which step to proceed to.</param> /// <returns></returns> public override async Task <CompletionResult> Complete(string data, Guid?activityResultID) { if (!activityResultID.HasValue) { activityResultID = SaveResultID; } var task = PmnTask.GetActiveTaskForRequestActivity(_entity.ID, ID, db); if (activityResultID == SaveResultID) { await task.LogAsModifiedAsync(_workflow.Identity, db); await db.SaveChangesAsync(); return(new CompletionResult { ResultID = SaveResultID }); } else if (activityResultID == BulkEditResultID) { await task.LogAsModifiedAsync(_workflow.Identity, db); await db.SaveChangesAsync(); return(new CompletionResult { ResultID = BulkEditResultID }); } else if (activityResultID == RemoveDatamartsResultID) { Guid[] guids = data.Split(',').Select(s => Guid.Parse(s)).ToArray(); var routings = await db.RequestDataMarts.Where(dm => guids.Contains(dm.ID)).ToArrayAsync(); foreach (var routing in routings) { routing.Status = DTO.Enums.RoutingStatus.Canceled; } await task.LogAsModifiedAsync(_workflow.Identity, db); await db.SaveChangesAsync(); var originalStatus = _entity.Status; await db.SaveChangesAsync(); await db.Entry(_entity).ReloadAsync(); if (originalStatus != DTO.Enums.RequestStatuses.Complete && _entity.Status == DTO.Enums.RequestStatuses.Complete) { await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Complete); } return(new CompletionResult { ResultID = RemoveDatamartsResultID }); } else if (activityResultID == CompleteRoutingResultID) { var uiResponse = Newtonsoft.Json.JsonConvert.DeserializeObject <WebResponseModel>(data); var routing = await db.RequestDataMarts.Include("Request").SingleOrDefaultAsync(dm => dm.ID == uiResponse.RequestDM && dm.RequestID == _entity.ID); var response = await db.Responses.SingleOrDefaultAsync(res => res.ID == uiResponse.Response && res.RequestDataMartID == uiResponse.RequestDM); response.ResponseTime = DateTime.UtcNow; response.RespondedByID = _workflow.Identity.ID; response.ResponseMessage = uiResponse.Comment; var originalRequestStatus = routing.Request.Status; var originalStatus = routing.Status; //We should only update the routing status if it is not already complete or modified. if (originalStatus != DTO.Enums.RoutingStatus.Completed && originalStatus != DTO.Enums.RoutingStatus.ResultsModified) { routing.Status = DTO.Enums.RoutingStatus.Completed; } if (routing.Status == DTO.Enums.RoutingStatus.Completed || routing.Status == DTO.Enums.RoutingStatus.ResultsModified) { try { var trackingTableProcessor = new DistributedRegressionTrackingTableProcessor(db); await trackingTableProcessor.Process(response); } catch (Exception ex) { //should not block if fails } } await db.SaveChangesAsync(); await db.Entry <RequestDataMart>(routing).ReloadAsync(); await db.Entry <Request>(_entity).ReloadAsync(); var completeStatuses = new[] { Lpp.Dns.DTO.Enums.RoutingStatus.Completed, Lpp.Dns.DTO.Enums.RoutingStatus.ResultsModified, Lpp.Dns.DTO.Enums.RoutingStatus.RequestRejected, Lpp.Dns.DTO.Enums.RoutingStatus.ResponseRejectedBeforeUpload, Lpp.Dns.DTO.Enums.RoutingStatus.ResponseRejectedAfterUpload, Lpp.Dns.DTO.Enums.RoutingStatus.AwaitingResponseApproval }; var incompletedRoutings = await db.RequestDataMarts.Where(dm => dm.RequestID == _entity.ID && dm.RoutingType != DTO.Enums.RoutingType.AnalysisCenter && !completeStatuses.Contains(dm.Status)).CountAsync(); if (incompletedRoutings == 0) { try { var routingProcessor = new DistributedRegressionRoutingProcessor(db, _workflow.Identity.ID); await routingProcessor.Process(routing); return(new CompletionResult { ResultID = CompleteRoutingResultToAC }); } catch (Exception ex) { throw; } } else { await task.LogAsModifiedAsync(_workflow.Identity, db); await db.SaveChangesAsync(); return(new CompletionResult { ResultID = CompleteRoutingResultID }); } } else if (activityResultID == TerminateResultID) { db.Requests.Remove(_entity); if (task != null) { db.Actions.Remove(task); } await db.SaveChangesAsync(); return(new CompletionResult { ResultID = TerminateResultID }); } else { throw new NotSupportedException(CommonMessages.ActivityResultNotSupported); } }
/// <summary> /// The Method to do what the User decieded /// </summary> /// <param name="data">The Data payload passed by the User</param> /// <param name="activityResultID">The Result ID Passed by the User to indicate which step to proceed to.</param> /// <returns></returns> public override async Task <CompletionResult> Complete(string data, Guid?activityResultID) { if (!activityResultID.HasValue) { activityResultID = SaveResultID; } var task = PmnTask.GetActiveTaskForRequestActivity(_entity.ID, ID, db); if (activityResultID == SaveResultID) { await task.LogAsModifiedAsync(_workflow.Identity, db); await db.SaveChangesAsync(); return(new CompletionResult { ResultID = SaveResultID }); } else if (activityResultID == RedistributeResultID) { if (!await db.HasPermissions <Project>(_workflow.Identity, _entity.ProjectID, Lpp.Dns.DTO.Security.PermissionIdentifiers.Project.ResubmitRequests)) { throw new System.Security.SecurityException(CommonMessages.RequirePermissionToResubmitRequest, Lpp.Dns.DTO.Security.PermissionIdentifiers.Project.ResubmitRequests.GetType()); } ResubmitRoutingsModel resubmitModel = Newtonsoft.Json.JsonConvert.DeserializeObject <ResubmitRoutingsModel>(data); var datamarts = await( from dm in db.RequestDataMarts.Include(dm => dm.Responses) where dm.RequestID == _entity.ID && dm.Responses.Any(r => resubmitModel.Responses.Contains(r.ID) || (r.ResponseGroupID.HasValue && resubmitModel.Responses.Contains(r.ResponseGroupID.Value))) select dm ).ToArrayAsync(); //for the last completed routing from the AC //look for the file_list.csv document, if does not exist use all files //if file_list.csv exists, only use the documents it specifies List <Guid> documentRevisionSetIDs = new List <Guid>(); var previousInputRequestDocuments = await(from d in db.Documents.AsNoTracking() join reqDoc in (from rd in db.RequestDocuments where rd.DocumentType == DTO.Enums.RequestDocumentType.Output && rd.Response.RequestDataMart.RoutingType == DTO.Enums.RoutingType.AnalysisCenter && rd.Response.Count == rd.Response.RequestDataMart.Responses.Where(rsp => rsp.RespondedByID.HasValue).Max(rsp => rsp.Count) && rd.Response.RequestDataMart.RequestID == _entity.ID select rd) on d.RevisionSetID equals reqDoc.RevisionSetID where d.ID == db.Documents.Where(dd => dd.RevisionSetID == d.RevisionSetID).OrderByDescending(dd => dd.MajorVersion).ThenByDescending(dd => dd.MinorVersion).ThenByDescending(dd => dd.BuildVersion).ThenByDescending(dd => dd.RevisionVersion).Select(dd => dd.ID).FirstOrDefault() select d).ToArrayAsync(); // look for the first document with kind == "DistributedRegression.FileList". Document fileListDocument = previousInputRequestDocuments.Where(d => !string.IsNullOrEmpty(d.Kind) && string.Equals("DistributedRegression.FileList", d.Kind, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); if (fileListDocument != null) { //only include the files indicated in the manifest byte[] fileListBytes = fileListDocument.GetData(db); using (var ms = new System.IO.MemoryStream(fileListBytes)) using (var reader = new System.IO.StreamReader(ms)) { //read the header line reader.ReadLine(); string line, filename; bool includeInDistribution = false; while (!reader.EndOfStream) { line = reader.ReadLine(); string[] split = line.Split(','); if (split.Length > 0) { filename = split[0].Trim(); if (split.Length > 1) { includeInDistribution = string.Equals(split[1].Trim(), "1"); } else { includeInDistribution = false; } if (includeInDistribution == false) { continue; } if (!string.IsNullOrEmpty(filename)) { Guid?revisionSetID = previousInputRequestDocuments.Where(d => string.Equals(d.FileName, filename, StringComparison.OrdinalIgnoreCase)).Select(d => d.RevisionSetID).FirstOrDefault(); if (revisionSetID.HasValue) { documentRevisionSetIDs.Add(revisionSetID.Value); } } } } reader.Close(); } } else { //include all documents documentRevisionSetIDs.AddRange(previousInputRequestDocuments.Select(d => d.RevisionSetID.Value).Distinct()); } DateTime reSubmittedOn = DateTime.UtcNow; foreach (var dm in datamarts) { var response = dm.AddResponse(_workflow.Identity.ID); response.SubmittedOn = reSubmittedOn; response.SubmitMessage = resubmitModel.ResubmissionMessage; dm.Status = DTO.Enums.RoutingStatus.Resubmitted; foreach (var revisionSetID in documentRevisionSetIDs) { db.RequestDocuments.Add(new RequestDocument { ResponseID = response.ID, RevisionSetID = revisionSetID, DocumentType = DTO.Enums.RequestDocumentType.Input }); } } await SetRequestStatus(DTO.Enums.RequestStatuses.Submitted); await task.LogAsModifiedAsync(_workflow.Identity, db); await db.SaveChangesAsync(); return(new CompletionResult { ResultID = RedistributeResultID }); } else if (activityResultID == BulkEditResultID) { await task.LogAsModifiedAsync(_workflow.Identity, db); await db.SaveChangesAsync(); return(new CompletionResult { ResultID = BulkEditResultID }); } else if (activityResultID == AddDatamartsResultID) { DTO.QueryComposer.QueryComposerRequestDTO requestDTO = Newtonsoft.Json.JsonConvert.DeserializeObject <DTO.QueryComposer.QueryComposerRequestDTO>(_entity.Query); var modularTerm = requestDTO.Where.Criteria.SelectMany(c => c.Terms.Where(t => t.Type == DistributedRegressionConfiguration.ModularProgramTermID)).FirstOrDefault(); var termValues = Newtonsoft.Json.JsonConvert.DeserializeObject <ModularProgramTermValues>(modularTerm.Values["Values"].ToString()); string[] datamartIDs = data.Split(','); var allTasks = await db.ActionReferences.Where(tr => tr.ItemID == _entity.ID && tr.Type == DTO.Enums.TaskItemTypes.Request && tr.Task.Type == DTO.Enums.TaskTypes.Task ) .Select(tr => tr.Task.ID).ToArrayAsync(); var attachments = await(from doc in db.Documents.AsNoTracking() join x in ( db.Documents.Where(dd => allTasks.Contains(dd.ItemID)) .GroupBy(k => k.RevisionSetID) .Select(k => k.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(y => y.ID).Distinct().FirstOrDefault()) ) on doc.ID equals x where allTasks.Contains(doc.ItemID) && doc.Kind == "Attachment.Input" orderby doc.ItemID descending, doc.RevisionSetID descending, doc.CreatedOn descending select doc).ToArrayAsync(); foreach (var guid in datamartIDs) { Guid dmGuid = new Guid(guid); var dm = RequestDataMart.Create(_entity.ID, dmGuid, _workflow.Identity.ID); dm.Status = DTO.Enums.RoutingStatus.Submitted; dm.DueDate = _entity.DueDate; dm.Priority = _entity.Priority; dm.RoutingType = DTO.Enums.RoutingType.DataPartner; _entity.DataMarts.Add(dm); Response rsp = dm.Responses.OrderByDescending(r => r.Count).FirstOrDefault(); //add the request document associations foreach (var revisionSetID in termValues.Documents.Select(d => d.RevisionSetID)) { db.RequestDocuments.Add(new RequestDocument { DocumentType = DTO.Enums.RequestDocumentType.Input, ResponseID = rsp.ID, RevisionSetID = revisionSetID }); } foreach (var attachment in attachments) { db.RequestDocuments.Add(new RequestDocument { RevisionSetID = attachment.RevisionSetID.Value, ResponseID = rsp.ID, DocumentType = DTO.Enums.RequestDocumentType.AttachmentInput }); } } await task.LogAsModifiedAsync(_workflow.Identity, db); await db.SaveChangesAsync(); return(new CompletionResult { ResultID = AddDatamartsResultID }); } else if (activityResultID == RemoveDatamartsResultID) { Guid[] guids = data.Split(',').Select(s => Guid.Parse(s)).ToArray(); var routings = await db.RequestDataMarts.Where(dm => guids.Contains(dm.ID)).ToArrayAsync(); foreach (var routing in routings) { routing.Status = DTO.Enums.RoutingStatus.Canceled; } await task.LogAsModifiedAsync(_workflow.Identity, db); await db.SaveChangesAsync(); var originalStatus = _entity.Status; await db.SaveChangesAsync(); await db.Entry(_entity).ReloadAsync(); if (originalStatus != DTO.Enums.RequestStatuses.Complete && _entity.Status == DTO.Enums.RequestStatuses.Complete) { await NotifyRequestStatusChanged(originalStatus, DTO.Enums.RequestStatuses.Complete); } return(new CompletionResult { ResultID = RemoveDatamartsResultID }); } else if (activityResultID == CompleteRoutingResultID) { var uiResponse = Newtonsoft.Json.JsonConvert.DeserializeObject <WebResponseModel>(data); var routing = await db.RequestDataMarts.Include("Request").SingleOrDefaultAsync(dm => dm.ID == uiResponse.RequestDM && dm.RequestID == _entity.ID); var response = await db.Responses.SingleOrDefaultAsync(res => res.ID == uiResponse.Response && res.RequestDataMartID == uiResponse.RequestDM); response.ResponseTime = DateTime.UtcNow; response.RespondedByID = _workflow.Identity.ID; response.ResponseMessage = uiResponse.Comment; var originalRequestStatus = routing.Request.Status; var originalStatus = routing.Status; //We should only update the routing status if it is not already complete or modified. if (originalStatus != DTO.Enums.RoutingStatus.Completed && originalStatus != DTO.Enums.RoutingStatus.ResultsModified) { routing.Status = DTO.Enums.RoutingStatus.Completed; } if (routing.Status == DTO.Enums.RoutingStatus.Completed || routing.Status == DTO.Enums.RoutingStatus.ResultsModified) { try { var trackingTableProcessor = new DistributedRegressionTrackingTableProcessor(db); await trackingTableProcessor.Process(response); } catch (Exception ex) { //should not block if fails } } await db.SaveChangesAsync(); await db.Entry <RequestDataMart>(routing).ReloadAsync(); await db.Entry <Request>(_entity).ReloadAsync(); var completeStatuses = new[] { Lpp.Dns.DTO.Enums.RoutingStatus.Completed, Lpp.Dns.DTO.Enums.RoutingStatus.ResultsModified, Lpp.Dns.DTO.Enums.RoutingStatus.RequestRejected, Lpp.Dns.DTO.Enums.RoutingStatus.ResponseRejectedBeforeUpload, Lpp.Dns.DTO.Enums.RoutingStatus.ResponseRejectedAfterUpload, Lpp.Dns.DTO.Enums.RoutingStatus.AwaitingResponseApproval }; var incompletedRoutings = await db.RequestDataMarts.Where(dm => dm.RequestID == _entity.ID && dm.RoutingType != DTO.Enums.RoutingType.AnalysisCenter && !completeStatuses.Contains(dm.Status)).CountAsync(); if (incompletedRoutings == 0) { try { var routingProcessor = new DistributedRegressionRoutingProcessor(db, _workflow.Identity.ID); await routingProcessor.Process(routing); return(new CompletionResult { ResultID = CompleteRoutingResultToAC }); } catch (Exception ex) { throw; } } else { await task.LogAsModifiedAsync(_workflow.Identity, db); await db.SaveChangesAsync(); return(new CompletionResult { ResultID = CompleteRoutingResultID }); } } else if (activityResultID == TerminateResultID) { db.Requests.Remove(_entity); if (task != null) { db.Actions.Remove(task); } await db.SaveChangesAsync(); return(new CompletionResult { ResultID = TerminateResultID }); } else { throw new NotSupportedException(CommonMessages.ActivityResultNotSupported); } }
public async Task <DMCRoutingStatusProcessorResult> UpdateStatusAsync(dmc.Criteria.SetRequestStatusData data) { PermissionDefinition permission = data.Status == dmc.Enums.DMCRoutingStatus.Hold ? PermissionIdentifiers.DataMartInProject.HoldRequest : (data.Status == dmc.Enums.DMCRoutingStatus.RequestRejected ? PermissionIdentifiers.DataMartInProject.RejectRequest : PermissionIdentifiers.DataMartInProject.UploadResults); bool hasPermission = await CheckPermission(data.RequestID, data.DataMartID, permission, Identity.ID); if (hasPermission == false) { string message = data.Status == dmc.Enums.DMCRoutingStatus.Hold ? "You do not have permission to change the status of this request to Hold" : (data.Status == dmc.Enums.DMCRoutingStatus.RequestRejected ? "You do not have permission to change the status of this request to Rejected" : "You do not have permission to upload results."); return(new DMCRoutingStatusProcessorResult(HttpStatusCode.Forbidden, message)); } //var currentResponse = await DataContext.Responses.Include(rsp => rsp.RequestDataMart).Where(rsp => rsp.RequestDataMart.RequestID == data.RequestID && rsp.RequestDataMart.DataMartID == data.DataMartID && rsp.Count == rsp.RequestDataMart.Responses.Select(x => x.Count).Max()).FirstOrDefaultAsync(); var details = await( from rsp in DataContext.Responses join rdm in DataContext.RequestDataMarts on rsp.RequestDataMartID equals rdm.ID join r in DataContext.Requests on rdm.RequestID equals r.ID where rdm.RequestID == data.RequestID && rdm.DataMartID == data.DataMartID && rsp.Count == rdm.Responses.Select(x => x.Count).Max() select new { Response = rsp, Routing = rdm, Request = r } ).FirstOrDefaultAsync(); if (details == null) { return(new DMCRoutingStatusProcessorResult(HttpStatusCode.NotFound, "Unable to determine the routing information based on the specified RequestID and DataMart ID.")); } var currentResponse = details.Response; var routing = details.Routing; var request = details.Request; var orginalRequestStatus = request.Status; var originalStatus = routing.Status; hasPermission = await CheckPermission(data.RequestID, data.DataMartID, PermissionIdentifiers.DataMartInProject.SkipResponseApproval, request.CreatedByID); if (originalStatus == DTO.Enums.RoutingStatus.Hold && data.Status == dmc.Enums.DMCRoutingStatus.Submitted && currentResponse.Count > 1) { routing.Status = DTO.Enums.RoutingStatus.Resubmitted; } else if (originalStatus == DTO.Enums.RoutingStatus.Completed || originalStatus == DTO.Enums.RoutingStatus.ResultsModified) { routing.Status = hasPermission ? DTO.Enums.RoutingStatus.ResultsModified : DTO.Enums.RoutingStatus.AwaitingResponseApproval; } else { routing.Status = (Lpp.Dns.DTO.Enums.RoutingStatus)((int)data.Status); if (routing.Status == DTO.Enums.RoutingStatus.AwaitingResponseApproval) { if (hasPermission) { routing.Status = DTO.Enums.RoutingStatus.Completed; } } } //updating the UpdatedOn property of the routing so that logs will get processed and will allow for status change notification to go out if further uploads are done while status is ResultsModified. routing.UpdatedOn = DateTime.UtcNow; routing.Properties = data.Properties == null ? null : "<P>" + string.Join("", from p in data.Properties where !string.IsNullOrEmpty(p.Name) select string.Format("<V Key=\"{0}\">{1}</V>", p.Name, p.Value)) + "</P>"; currentResponse.ResponseMessage = data.Message; //only set the response time and ID if the response is completed var completeStatuses = new[] { Lpp.Dns.DTO.Enums.RoutingStatus.Completed, Lpp.Dns.DTO.Enums.RoutingStatus.ResultsModified, Lpp.Dns.DTO.Enums.RoutingStatus.RequestRejected, Lpp.Dns.DTO.Enums.RoutingStatus.ResponseRejectedBeforeUpload, Lpp.Dns.DTO.Enums.RoutingStatus.ResponseRejectedAfterUpload, Lpp.Dns.DTO.Enums.RoutingStatus.AwaitingResponseApproval, Lpp.Dns.DTO.Enums.RoutingStatus.Hold }; bool routingIsComplete = completeStatuses.Contains(routing.Status); if (routingIsComplete) { currentResponse.ResponseTime = DateTime.UtcNow; currentResponse.RespondedByID = Identity.ID; } if ((routing.Status == DTO.Enums.RoutingStatus.Completed || routing.Status == DTO.Enums.RoutingStatus.ResultsModified) && routing.Request.WorkflowID.HasValue) { try { var trackingTableProcessor = new DistributedRegressionTrackingTableProcessor(DataContext); await trackingTableProcessor.Process(currentResponse); } catch (Exception ex) { //should not block if fails Logger.Error(string.Format("Error processing tracking table for response ID: {0}\r\n{1}", currentResponse.ID, Lpp.Utilities.ExceptionHelpers.UnwindException(ex, true)), ex.InnerException ?? ex); } } await DataContext.SaveChangesAsync(); await DataContext.Entry(request).ReloadAsync(); if (!data.Message.IsEmpty()) { var log = await DataContext.LogsRoutingStatusChange.OrderByDescending(x => x.TimeStamp).FirstOrDefaultAsync(x => x.ResponseID == currentResponse.ID); log.Description += $" {data.Message}"; await DataContext.SaveChangesAsync(); } if (request.WorkflowID.HasValue && request.WorkflowID.Value == VerticalDistributedRegressionWorkflowID && (routing.Status == DTO.Enums.RoutingStatus.Completed || routing.Status == DTO.Enums.RoutingStatus.ResultsModified)) { try { await DataContext.Entry(routing).Reference(r => r.Request).LoadAsync(); var routingProcessor = new VerticalDistributedRegressionRoutingProcessor(DataContext, Identity.ID); await routingProcessor.Process(routing); } catch (Exception ex) { Logger.Error(string.Format("Error processing distributed regression route transistion for request ID: {0}\r\n{1}", routing.RequestID, Lpp.Utilities.ExceptionHelpers.UnwindException(ex, true)), ex.InnerException ?? ex); throw; } } else if (routingIsComplete && request.Status == DTO.Enums.RequestStatuses.Complete && request.WorkflowID.HasValue) { if (request.WorkflowID.Value == HorizontalDistributedRegressionWorkflowID && (routing.Status == DTO.Enums.RoutingStatus.Completed || routing.Status == DTO.Enums.RoutingStatus.ResultsModified)) { try { await DataContext.Entry(routing).Reference(r => r.Request).LoadAsync(); var routingProcessor = new DistributedRegressionRoutingProcessor(DataContext, Identity.ID); await routingProcessor.Process(routing); } catch (Exception ex) { Logger.Error(string.Format("Error processing distributed regression route transistion for request ID: {0}\r\n{1}", routing.RequestID, Lpp.Utilities.ExceptionHelpers.UnwindException(ex, true)), ex.InnerException ?? ex); throw; } } //reload the request to get the current request status. await DataContext.Entry(request).ReloadAsync(); if (request.Status == DTO.Enums.RequestStatuses.Complete) { //send the request status complete notification var requestStatusLogger = new Dns.Data.RequestLogConfiguration(); string[] emailText = await requestStatusLogger.GenerateRequestStatusChangedEmailContent(DataContext, request.ID, Identity.ID, orginalRequestStatus, request.Status); var logItems = requestStatusLogger.GenerateRequestStatusEvents(DataContext, Identity, false, orginalRequestStatus, request.Status, request.ID, emailText[1], emailText[0], "Request Status Changed"); await DataContext.SaveChangesAsync(); await Task.Run(() => { List <Utilities.Logging.Notification> notifications = new List <Utilities.Logging.Notification>(); foreach (Lpp.Dns.Data.Audit.RequestStatusChangedLog logitem in logItems) { var items = requestStatusLogger.CreateNotifications(logitem, DataContext, true); if (items != null && items.Any()) { notifications.AddRange(items); } } if (notifications.Any()) { requestStatusLogger.SendNotification(notifications); } }); } } return(new DMCRoutingStatusProcessorResult()); }
public async Task CreateLogForNonDistributedRegressionRequest() { Guid requestID = Guid.Parse("C8702FA2-C9AC-4CC4-82BE-A84D0118904C"); var Identity = new Lpp.Utilities.Security.ApiIdentity(Guid.Parse("9F400001-FAD6-4E84-8933-A2380151C648"), "jmalenfant", null); using (var DataContext = new Dns.Data.DataContext()) { var requestQuery = DataContext.Secure <Request>(Identity).Where(r => r.ID == requestID); var builder = new Lpp.Dns.Data.DistributedRegressionTracking.EnhancedEventLogBuilder(); builder.RequestStatusChangeEvents = async() => { var evts = await(from l in DataContext.LogsRequestStatusChanged let dtTimestamp = DbFunctions.CreateDateTime(l.TimeStamp.Year, l.TimeStamp.Month, l.TimeStamp.Day, l.TimeStamp.Hour, l.TimeStamp.Minute, l.TimeStamp.Second) where requestQuery.Any() && l.RequestID == requestID select new { l.TimeStamp, //treat the step as the lowest response count where the response is submitted after the status change log item timestamp or zero Step = DataContext.Responses.Where(rsp => rsp.RequestDataMart.RequestID == l.RequestID && rsp.SubmittedOn >= dtTimestamp).Select(rsp => (int?)rsp.Count).Min() ?? 0, l.Description }).ToArrayAsync(); return(evts.Select(l => new EnhancedEventLogItemDTO { Timestamp = l.TimeStamp.DateTime, Source = string.Empty, Step = l.Step, Description = l.Description })); }; builder.RoutingStatusChangeEvents = async() => { var evts = await(from l in DataContext.LogsRoutingStatusChange let dtTimestamp = DbFunctions.CreateDateTime(l.TimeStamp.Year, l.TimeStamp.Month, l.TimeStamp.Day, l.TimeStamp.Hour, l.TimeStamp.Minute, l.TimeStamp.Second) where requestQuery.Any() && l.RequestDataMart.RequestID == requestID select new { Timestamp = l.TimeStamp, Source = l.RequestDataMart.DataMart.Name, Description = l.Description, //treat the step as the maximum response count where the response is submitted before the status change log item timestamp or zero Step = l.RequestDataMart.Responses.Where(rsp => rsp.SubmittedOn <= dtTimestamp).Select(rsp => (int?)rsp.Count).Max() ?? 0 }).ToArrayAsync(); return(evts.Select(l => new EnhancedEventLogItemDTO { Timestamp = l.Timestamp.DateTime, Source = l.Source, Step = l.Step, Description = l.Description })); }; builder.DocumentUploadEvents = async() => { var lastDocumentUpload = await(from rsp in DataContext.Responses let lastDoc = (from rd in DataContext.RequestDocuments join doc in DataContext.Documents on rd.RevisionSetID equals doc.RevisionSetID where rd.ResponseID == rsp.ID && rd.DocumentType == RequestDocumentType.Output orderby doc.CreatedOn descending select doc).FirstOrDefault() where rsp.RequestDataMart.RequestID == requestID && requestQuery.Any() && rsp.ResponseTime != null && lastDoc != null select new { Iteration = rsp.Count, DataMart = rsp.RequestDataMart.DataMart.Name, DocumentCreatedOn = lastDoc.CreatedOn }).ToArrayAsync(); return(lastDocumentUpload.Select(l => new EnhancedEventLogItemDTO { Timestamp = l.DocumentCreatedOn, Source = l.DataMart, Step = l.Iteration, Description = "Files finished uploading" })); }; ////parse latest AC tracking table ////parse any DP tracking tables that are iteration a head of AC var dataPartners = await DataContext.RequestDataMarts.Where(rdm => rdm.RequestID == requestID).Select(rdm => new { rdm.DataMart.Name, Identifier = (rdm.DataMart.DataPartnerIdentifier ?? rdm.DataMart.Acronym), rdm.RoutingType }).ToDictionaryAsync(k => k.Identifier); builder.TrackingTableEvents = async() => { //get the ID of the latest Analysis tracking document var latestACTrackingDocumentID = await(from rd in DataContext.RequestDocuments join doc in DataContext.Documents on rd.RevisionSetID equals doc.RevisionSetID where rd.Response.RequestDataMart.RequestID == requestID && requestQuery.Any() && rd.Response.RequestDataMart.RoutingType == RoutingType.AnalysisCenter && rd.Response.Count == rd.Response.RequestDataMart.Responses.Max(rsp => rsp.Count) && doc.Kind == "DistributedRegression.TrackingTable" orderby doc.MajorVersion, doc.MinorVersion, doc.BuildVersion, doc.RevisionVersion descending select doc.ID).FirstOrDefaultAsync(); if (latestACTrackingDocumentID == default(Guid)) { return(Array.Empty <EnhancedEventLogItemDTO>()); } IEnumerable <Data.DistributedRegressionTracking.TrackingTableItem> trackingTableItems; using (var db = new DataContext()) using (var stream = new Data.Documents.DocumentStream(db, latestACTrackingDocumentID)) { trackingTableItems = await DistributedRegressionTrackingTableProcessor.Read(stream); } List <EnhancedEventLogItemDTO> logItems = new List <EnhancedEventLogItemDTO>(trackingTableItems.Count()); int lastIteration = trackingTableItems.Max(t => t.Iteration); foreach (var partnerEntries in trackingTableItems.GroupBy(k => k.DataPartnerCode)) { var dataPartnerName = dataPartners[TranslatePartnerIdentifier(partnerEntries.Key)].Name; foreach (var iteration in partnerEntries.GroupBy(k => k.Iteration)) { if (iteration.Key == 0 || iteration.Key == lastIteration) { //read from the last start time logItems.Add(new EnhancedEventLogItemDTO { Step = iteration.Key, Description = "SAS program execution begin", Source = dataPartnerName, Timestamp = iteration.Max(l => l.Start) }); } else { //if DP read the latest start //if AC read the 2nd last start time //TODO: talk to Qoua - I don't think this is valid logic/rule logItems.Add(new EnhancedEventLogItemDTO { Step = iteration.Key, Description = "SAS program execution begin", Source = dataPartnerName, Timestamp = iteration.Max(l => l.Start) }); } //read the last end time logItems.Add(new EnhancedEventLogItemDTO { Step = iteration.Key, Description = "SAS program execution complete, output files written.", Source = dataPartnerName, Timestamp = iteration.Max(l => l.End) }); } ; } ; return(logItems); }; //builder.AdapterLoggedEvents = async () => { // List<EnhancedEventLogItemDTO> logItems = new List<EnhancedEventLogItemDTO>(); // //get the adapter event logs, will need to know the response iteration, and the datamart name // var adapterLogs = await (from rd in DataContext.RequestDocuments // let doc = (from d in DataContext.Documents where d.RevisionSetID == rd.RevisionSetID && d.Kind == "DistributedRegression.AdapterEventLog" select d).DefaultIfEmpty() // where rd.DocumentType == RequestDocumentType.Output // && rd.Response.RequestDataMart.RequestID == requestID // && requestQuery.Any() // && doc.Any() // select // new // { // ResponseID = rd.ResponseID, // ResponseIteration = rd.Response.Count, // DataMart = rd.Response.RequestDataMart.DataMart.Name, // DocumentID = doc.OrderByDescending(d => d.MajorVersion).ThenByDescending(d => d.MinorVersion).ThenByDescending(d => d.BuildVersion).ThenByDescending(d => d.RevisionVersion).Select(d => d.ID).FirstOrDefault() // }).ToArrayAsync(); // foreach (var log in adapterLogs) // { // //get the log content // using (var db = new DataContext()) // using (var streamReader = new StreamReader(new Data.Documents.DocumentStream(db, log.DocumentID))) // using (var reader = new Newtonsoft.Json.JsonTextReader(streamReader)) // { // var serializer = new Newtonsoft.Json.JsonSerializer(); // var adapterEvents = serializer.Deserialize<IEnumerable<EventLogItem>>(reader) // .Select(al => new EnhancedEventLogItemDTO // { // Step = log.ResponseIteration, // Source = log.DataMart, // Description = al.Description, // Timestamp = al.Timestamp // }).ToArray(); // if (adapterEvents.Length > 0) // { // logItems.AddRange(adapterEvents); // } // } // } // return logItems; //}; var eventLog = await builder.GetItems(); StringBuilder sb = new StringBuilder(); foreach (var item in eventLog) { //Console.WriteLine("{0}\t{1:o}\t{2}\t{3}", item.Step, item.Timestamp, item.Source, item.Description); //Logger.InfoFormat("{0}\t{1:o}\t{2}\t{3}\r\n", item.Step, item.Timestamp, item.Source, item.Description); sb.AppendLine(string.Format("{0}\t{1:o}\t{2}\t{3}", item.Step, item.Timestamp, item.Source, item.Description)); } Logger.Info("Event Log:\n" + sb.ToString()); } }