diff --git a/server/AyaNova/Controllers/ExportController.cs b/server/AyaNova/Controllers/ExportController.cs index efacdc02..b69129cc 100644 --- a/server/AyaNova/Controllers/ExportController.cs +++ b/server/AyaNova/Controllers/ExportController.cs @@ -102,7 +102,7 @@ namespace AyaNova.Api.Controllers case "csv": using (var w = new ChoCSVWriter(outputSourceFullPath).WithFirstLineHeader()) { - var dat = await ((IExportAbleObject)biz).GetExportData(selectedRequest, DateTime.UtcNow.AddMinutes(ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT)); + var dat = await ((IExportAbleObject)biz).GetExportData(selectedRequest, Guid.Empty);//todo: jobify w.Write(ToDynamicList(dat)); } break; @@ -110,7 +110,7 @@ namespace AyaNova.Api.Controllers using (StreamWriter file = System.IO.File.CreateText(outputSourceFullPath)) using (JsonTextWriter writer = new JsonTextWriter(file)) { - var dat = await ((IExportAbleObject)biz).GetExportData(selectedRequest, DateTime.UtcNow.AddMinutes(ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT)); + var dat = await ((IExportAbleObject)biz).GetExportData(selectedRequest, Guid.Empty);//todo: jobify dat.WriteTo(writer); } break; diff --git a/server/AyaNova/Controllers/ReportController.cs b/server/AyaNova/Controllers/ReportController.cs index aaa99f67..331ebe28 100644 --- a/server/AyaNova/Controllers/ReportController.cs +++ b/server/AyaNova/Controllers/ReportController.cs @@ -178,7 +178,7 @@ namespace AyaNova.Api.Controllers JArray reportData; try { - reportData = await biz.GetReportData(selectedRequest, DateTime.UtcNow.AddMinutes(ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT)); + reportData = await biz.GetReportDataForReportDesigner(selectedRequest); if (reportData == null) return BadRequest(new ApiErrorResponse(biz.Errors)); else diff --git a/server/AyaNova/biz/ContractBiz.cs b/server/AyaNova/biz/ContractBiz.cs index f4e2fccd..162e012f 100644 --- a/server/AyaNova/biz/ContractBiz.cs +++ b/server/AyaNova/biz/ContractBiz.cs @@ -480,7 +480,7 @@ MULTIPLE discount / markup ITEMS //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -510,8 +510,7 @@ MULTIPLE discount / markup ITEMS var PreTrans = await TranslationBiz.GetSubsetStaticAsync(new List { "TimeSpanDays", "TimeSpanHours", "TimeSpanMinutes", "TimeSpanSeconds" }, UserTranslationId); foreach (Contract w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w, ContractOverrideTypeEnumList, PreTrans); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -560,11 +559,11 @@ MULTIPLE discount / markup ITEMS // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/CustomerBiz.cs b/server/AyaNova/biz/CustomerBiz.cs index 17676927..1b2886e9 100644 --- a/server/AyaNova/biz/CustomerBiz.cs +++ b/server/AyaNova/biz/CustomerBiz.cs @@ -329,7 +329,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -354,8 +354,7 @@ namespace AyaNova.Biz foreach (Customer w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -402,11 +401,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } public async Task> ImportData(JArray ja) diff --git a/server/AyaNova/biz/CustomerNoteBiz.cs b/server/AyaNova/biz/CustomerNoteBiz.cs index 34fc4d65..05b2f1a2 100644 --- a/server/AyaNova/biz/CustomerNoteBiz.cs +++ b/server/AyaNova/biz/CustomerNoteBiz.cs @@ -180,7 +180,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -194,8 +194,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (CustomerNote w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w); var jo = JObject.FromObject(w); ReportData.Add(jo); @@ -215,11 +214,11 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } //////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/server/AyaNova/biz/CustomerServiceRequestBiz.cs b/server/AyaNova/biz/CustomerServiceRequestBiz.cs index 59a4f92f..1602bb6a 100644 --- a/server/AyaNova/biz/CustomerServiceRequestBiz.cs +++ b/server/AyaNova/biz/CustomerServiceRequestBiz.cs @@ -290,7 +290,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -317,8 +317,7 @@ namespace AyaNova.Biz foreach (CustomerServiceRequest w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w, CustomerServiceRequestStatusEnumList, CustomerServiceRequestPriorityEnumList); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -346,11 +345,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } public async Task> ImportData(JArray ja) diff --git a/server/AyaNova/biz/HeadOfficeBiz.cs b/server/AyaNova/biz/HeadOfficeBiz.cs index 3afdb62c..3167e54c 100644 --- a/server/AyaNova/biz/HeadOfficeBiz.cs +++ b/server/AyaNova/biz/HeadOfficeBiz.cs @@ -286,7 +286,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -300,8 +300,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (HeadOffice w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -323,11 +322,11 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/IExportAbleObject.cs b/server/AyaNova/biz/IExportAbleObject.cs index e217504a..74f3e1c4 100644 --- a/server/AyaNova/biz/IExportAbleObject.cs +++ b/server/AyaNova/biz/IExportAbleObject.cs @@ -13,7 +13,7 @@ namespace AyaNova.Biz //Get items indicated in id list in exportable format //called by ExportBiz rendering code - Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry); + Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId); const int EXPORT_DATA_BATCH_SIZE = 100; } diff --git a/server/AyaNova/biz/IReportAbleObject.cs b/server/AyaNova/biz/IReportAbleObject.cs index ffd783e0..baeddc2c 100644 --- a/server/AyaNova/biz/IReportAbleObject.cs +++ b/server/AyaNova/biz/IReportAbleObject.cs @@ -12,7 +12,7 @@ namespace AyaNova.Biz //Get items indicated in id list in report format //called by ReportBiz rendering code - Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry); + Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId); const int REPORT_DATA_BATCH_SIZE = 100; diff --git a/server/AyaNova/biz/JobsBiz.cs b/server/AyaNova/biz/JobsBiz.cs index 1d9ca209..a77c106b 100644 --- a/server/AyaNova/biz/JobsBiz.cs +++ b/server/AyaNova/biz/JobsBiz.cs @@ -182,15 +182,15 @@ namespace AyaNova.Biz if (ActivelyProcessing) { //System.Diagnostics.Debug.WriteLine("ProcessJobs called but actively processing other jobs so returning"); - log.LogDebug("ProcessJobs called but actively processing other jobs so returning"); + log.LogTrace("ProcessJobs called but actively processing other jobs so returning"); return; } if (!KeepOnWorking()) return; ActivelyProcessing = true; - log.LogDebug("Processing internal jobs"); + log.LogTrace("Processing internal jobs"); try { - log.LogDebug("Processing level 1 internal jobs"); + log.LogTrace("Processing level 1 internal jobs"); //### Critical internal jobs, these run even if there is a license related serverlock //LICENSE FETCH await CoreJobLicense.DoWorkAsync(); @@ -202,7 +202,7 @@ namespace AyaNova.Biz ApiServerState serverState = ServiceProviderProvider.ServerState; if (!KeepOnWorking()) return; - log.LogDebug("Processing level 2 internal jobs"); + log.LogTrace("Processing level 2 internal jobs"); // #if (DEBUG) // log.LogInformation("Processing semi-critical internal jobs (backup, pm, notification etc)"); @@ -239,7 +239,7 @@ namespace AyaNova.Biz if (!KeepOnWorking()) return; - log.LogDebug("Processing exclusive dynamic jobs"); + log.LogTrace("Processing exclusive dynamic jobs"); //BIZOBJECT DYNAMIC JOBS //get a list of exclusive jobs that are due to happen @@ -271,7 +271,7 @@ namespace AyaNova.Biz /////////////////////////////////////// //NON-EXCLUSIVE JOBS // - log.LogDebug("Processing non-exclusive dynamic jobs"); + log.LogTrace("Processing non-exclusive dynamic jobs"); if (!KeepOnWorking()) return; //These fire and forget but use a technique to bubble up exceptions anyway List sharedJobs = await GetReadyJobsNotExlusiveOnlyAsync(); diff --git a/server/AyaNova/biz/LoanUnitBiz.cs b/server/AyaNova/biz/LoanUnitBiz.cs index 839d11f2..e0d3040c 100644 --- a/server/AyaNova/biz/LoanUnitBiz.cs +++ b/server/AyaNova/biz/LoanUnitBiz.cs @@ -273,7 +273,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -287,8 +287,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (LoanUnit w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -310,11 +309,11 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/MemoBiz.cs b/server/AyaNova/biz/MemoBiz.cs index 5b0f5f4f..ff8674e2 100644 --- a/server/AyaNova/biz/MemoBiz.cs +++ b/server/AyaNova/biz/MemoBiz.cs @@ -278,7 +278,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -292,8 +292,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (Memo w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -318,11 +317,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } public async Task> ImportData(JArray ja) diff --git a/server/AyaNova/biz/PMBiz.cs b/server/AyaNova/biz/PMBiz.cs index 54806f19..510117dd 100644 --- a/server/AyaNova/biz/PMBiz.cs +++ b/server/AyaNova/biz/PMBiz.cs @@ -814,7 +814,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //quote reports for entire quote or just sub parts all go through here //if the ayatype is a descendant of the quote then only the portion of the quote from that descendant directly up to the header will be populated and returned @@ -833,8 +833,7 @@ namespace AyaNova.Biz foreach (PM w in batchResults) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; var jo = JObject.FromObject(w); //PM header custom fields @@ -955,11 +954,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/PartAssemblyBiz.cs b/server/AyaNova/biz/PartAssemblyBiz.cs index b6ddd58e..108c1355 100644 --- a/server/AyaNova/biz/PartAssemblyBiz.cs +++ b/server/AyaNova/biz/PartAssemblyBiz.cs @@ -326,7 +326,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -340,8 +340,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (PartAssembly w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -364,11 +363,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } public async Task> ImportData(JArray ja) diff --git a/server/AyaNova/biz/PartBiz.cs b/server/AyaNova/biz/PartBiz.cs index a6e9f7fe..6646998c 100644 --- a/server/AyaNova/biz/PartBiz.cs +++ b/server/AyaNova/biz/PartBiz.cs @@ -500,7 +500,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -514,8 +514,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (Part w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -545,11 +544,11 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } public async Task> ImportData(JArray ja) diff --git a/server/AyaNova/biz/PartInventoryBiz.cs b/server/AyaNova/biz/PartInventoryBiz.cs index f1106835..d4b60660 100644 --- a/server/AyaNova/biz/PartInventoryBiz.cs +++ b/server/AyaNova/biz/PartInventoryBiz.cs @@ -255,7 +255,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -279,8 +279,7 @@ namespace AyaNova.Biz foreach (PartInventory w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w, AyaTypesEnumList, command); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -311,11 +310,11 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/PartInventoryDataListBiz.cs b/server/AyaNova/biz/PartInventoryDataListBiz.cs index e6ba387c..5a78fb33 100644 --- a/server/AyaNova/biz/PartInventoryDataListBiz.cs +++ b/server/AyaNova/biz/PartInventoryDataListBiz.cs @@ -35,7 +35,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -56,8 +56,7 @@ namespace AyaNova.Biz foreach (ViewPartInventoryList w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; var jo = JObject.FromObject(w); ReportData.Add(jo); } @@ -70,11 +69,11 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/PartInventoryRequestDataListBiz.cs b/server/AyaNova/biz/PartInventoryRequestDataListBiz.cs index 520a5fa9..a682528e 100644 --- a/server/AyaNova/biz/PartInventoryRequestDataListBiz.cs +++ b/server/AyaNova/biz/PartInventoryRequestDataListBiz.cs @@ -35,7 +35,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -56,8 +56,7 @@ namespace AyaNova.Biz foreach (ViewPartInventoryRequestList w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; var jo = JObject.FromObject(w); ReportData.Add(jo); @@ -72,11 +71,11 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/PartWarehouseBiz.cs b/server/AyaNova/biz/PartWarehouseBiz.cs index d953a3f9..4a458aa9 100644 --- a/server/AyaNova/biz/PartWarehouseBiz.cs +++ b/server/AyaNova/biz/PartWarehouseBiz.cs @@ -285,7 +285,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -299,8 +299,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (PartWarehouse w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) jo["CustomFields"] = JObject.Parse((string)jo["CustomFields"]); @@ -316,11 +315,11 @@ namespace AyaNova.Biz // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/ProjectBiz.cs b/server/AyaNova/biz/ProjectBiz.cs index 3a074c1b..e3c2a742 100644 --- a/server/AyaNova/biz/ProjectBiz.cs +++ b/server/AyaNova/biz/ProjectBiz.cs @@ -274,7 +274,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -288,8 +288,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (Project w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -313,11 +312,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } public async Task> ImportData(JArray ja) diff --git a/server/AyaNova/biz/PurchaseOrderBiz.cs b/server/AyaNova/biz/PurchaseOrderBiz.cs index ca5de6e8..cc812dae 100644 --- a/server/AyaNova/biz/PurchaseOrderBiz.cs +++ b/server/AyaNova/biz/PurchaseOrderBiz.cs @@ -778,7 +778,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -792,8 +792,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (PurchaseOrder w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await SetDisplayFields(w, true); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -809,11 +808,11 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/QuoteBiz.cs b/server/AyaNova/biz/QuoteBiz.cs index 75a1b1d4..b4741757 100644 --- a/server/AyaNova/biz/QuoteBiz.cs +++ b/server/AyaNova/biz/QuoteBiz.cs @@ -790,7 +790,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //quote reports for entire quote or just sub parts all go through here //if the ayatype is a descendant of the quote then only the portion of the quote from that descendant directly up to the header will be populated and returned @@ -809,8 +809,7 @@ namespace AyaNova.Biz foreach (Quote w in batchResults) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; var jo = JObject.FromObject(w); //Quote header custom fields @@ -979,11 +978,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/ReminderBiz.cs b/server/AyaNova/biz/ReminderBiz.cs index e33b7719..41fc77c2 100644 --- a/server/AyaNova/biz/ReminderBiz.cs +++ b/server/AyaNova/biz/ReminderBiz.cs @@ -277,7 +277,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -291,8 +291,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (Reminder w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -313,11 +312,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } public async Task> ImportData(JArray ja) diff --git a/server/AyaNova/biz/ReportBiz.cs b/server/AyaNova/biz/ReportBiz.cs index 5da09244..96d728b5 100644 --- a/server/AyaNova/biz/ReportBiz.cs +++ b/server/AyaNova/biz/ReportBiz.cs @@ -283,9 +283,33 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORT DATA - //Data fetched to return to report designer for Client report design usage + //Data fetched to return to report render or for designer for Client report design usage - public async Task GetReportData(DataListSelectedRequest selectedRequest, DateTime renderTimeOutExpiry, bool requestIsCustomerWorkOrderReport = false) + public async Task GetReportDataForReportDesigner(DataListSelectedRequest selectedRequest) + { + var log = AyaNova.Util.ApplicationLogging.CreateLogger("ReportBiz::GetReportDataForReportDesigner"); + AuthorizationRoles effectiveRoles = CurrentUserRoles; + + if (selectedRequest.AType == AyaType.NoType) + { + AddError(ApiErrorCode.VALIDATION_REQUIRED, null, $"AType is required"); + return null; + } + + //Do we need to rehydrate the ID List from a DataList? + if (selectedRequest.SelectedRowIds.Length == 0) + selectedRequest.SelectedRowIds = await DataListSelectedProcessingOptions.RehydrateIdList(selectedRequest, ct, effectiveRoles, log, UserId, UserTranslationId); + + + log.LogDebug($"Instantiating biz object handler for {selectedRequest.AType}"); + var biz = BizObjectFactory.GetBizObject(selectedRequest.AType, ct, UserId, CurrentUserRoles, UserTranslationId); + log.LogDebug($"Fetching data for {selectedRequest.SelectedRowIds.Length} {selectedRequest.AType} items"); + return await ((IReportAbleObject)biz).GetReportData(selectedRequest, Guid.Empty);//Guid.empty signifies it's not a job calling it + } + + + + public async Task GetReportData(DataListSelectedRequest selectedRequest, Guid jobId, bool requestIsCustomerWorkOrderReport = false) { var log = AyaNova.Util.ApplicationLogging.CreateLogger("ReportBiz::GetReportData"); AuthorizationRoles effectiveRoles = CurrentUserRoles; @@ -306,464 +330,15 @@ namespace AyaNova.Biz if (selectedRequest.SelectedRowIds.Length == 0) selectedRequest.SelectedRowIds = await DataListSelectedProcessingOptions.RehydrateIdList(selectedRequest, ct, effectiveRoles, log, UserId, UserTranslationId); - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); - + if (!ReportRenderManager.KeepGoing(jobId)) + return null; log.LogDebug($"Instantiating biz object handler for {selectedRequest.AType}"); var biz = BizObjectFactory.GetBizObject(selectedRequest.AType, ct, UserId, CurrentUserRoles, UserTranslationId); log.LogDebug($"Fetching data for {selectedRequest.SelectedRowIds.Length} {selectedRequest.AType} items"); - return await ((IReportAbleObject)biz).GetReportData(selectedRequest, renderTimeOutExpiry); + return await ((IReportAbleObject)biz).GetReportData(selectedRequest, jobId); } - - //////////////////////////////////////////////////////////////////////////////////////////////// - //RENDER - // - - // public async Task RenderReport(DataListReportRequest reportRequest, DateTime renderTimeOutExpiry, string apiUrl) - // { - // var log = AyaNova.Util.ApplicationLogging.CreateLogger("RenderReport"); - // log.LogDebug($"ReportBiz::RenderReport id {reportRequest.ReportId}, timeout @ {renderTimeOutExpiry.ToString()}"); - - - - // //Customer User Report? - // bool RequestIsCustomerWorkOrderReport = false; - // if (reportRequest.ReportId == -100) - // { - // log.LogDebug("customer user report requested"); - // //get the user and workorder data and set the actual report id or return null if not found - // var woTags = await ct.WorkOrder.AsNoTracking().Where(x => x.Id == reportRequest.SelectedRowIds[0]).Select(x => x.Tags).FirstOrDefaultAsync(); - // if (woTags == null) return null; - // var cr = await UserBiz.CustomerUserEffectiveRightsAsync(UserId, woTags); - // if (cr.ThisWOEffectiveWOReportId == null) return null; - // reportRequest.ReportId = (long)cr.ThisWOEffectiveWOReportId; - // RequestIsCustomerWorkOrderReport = true; - // } - - // if (DateTime.UtcNow > renderTimeOutExpiry) - // throw new ReportRenderTimeOutException(); - - // //get report, vet security, see what we need before init in case of issue - // log.LogDebug($"get report from db"); - // var report = await ct.Report.FirstOrDefaultAsync(z => z.Id == reportRequest.ReportId); - // if (report == null) - // { - // AddError(ApiErrorCode.NOT_FOUND, "id"); - // return null; - // } - - // //If we get here via the /viewreport url in the client then there is no object type set so we need to set it here from the report - // if (reportRequest.AType == AyaType.NoType) - // { - // reportRequest.AType = report.AType; - // } - - - // AuthorizationRoles effectiveRoles = CurrentUserRoles; - - - // if (!RequestIsCustomerWorkOrderReport && !AyaNova.Api.ControllerHelpers.Authorized.HasReadFullRole(effectiveRoles, report.AType)) - // { - // log.LogDebug($"bail: user unauthorized"); - // AddError(ApiErrorCode.NOT_AUTHORIZED, null, $"User not authorized for {report.AType} type object"); - // return null; - // } - - // //Client meta data is required - // if (reportRequest.ClientMeta == null) - // { - // log.LogDebug($"bail: ClientMeta parameter is missing"); - // AddError(ApiErrorCode.VALIDATION_MISSING_PROPERTY, null, "ClientMeta parameter is missing and required to render report"); - // return null; - // } - - - - // //includeWoItemDescendants? - // reportRequest.IncludeWoItemDescendants = report.IncludeWoItemDescendants; - - // //Get data - // // #if (DEBUG) - // // log.LogInformation($"DBG: ReportBiz::RenderReport GetReportData"); - // // #endif - // log.LogDebug("Getting report data now"); - // var ReportData = await GetReportData(reportRequest, renderTimeOutExpiry, RequestIsCustomerWorkOrderReport); - // //if GetReportData errored then will return null so need to return that as well here - // if (ReportData == null) - // { - // log.LogDebug($"bail: ReportData == null"); - // return null; - // } - // // #if (DEBUG) - // // log.LogInformation($"DBG: ReportBiz::RenderReport got report data"); - // // #endif - // if (DateTime.UtcNow > renderTimeOutExpiry) - // throw new ReportRenderTimeOutException(); - // //initialization - // log.LogDebug("Initializing report rendering system"); - // bool AutoDownloadChromium = true; - // if (string.IsNullOrWhiteSpace(ServerBootConfig.AYANOVA_REPORT_RENDER_BROWSER_PATH)) - // { - // log.LogDebug($"Using default Chromium browser (downloaded)"); - // } - // else - // { - // log.LogDebug($"Using user specified Chromium browser at {ServerBootConfig.AYANOVA_REPORT_RENDER_BROWSER_PATH}"); - // AutoDownloadChromium = false; - // } - - // var ReportJSFolderPath = Path.Combine(ServerBootConfig.AYANOVA_CONTENT_ROOT_PATH, "resource", "rpt"); - - // var lo = new LaunchOptions { Headless = true }; - // if (!AutoDownloadChromium) - // { - // lo.ExecutablePath = ServerBootConfig.AYANOVA_REPORT_RENDER_BROWSER_PATH; - // /* - // troubleshooting links: - // https://developers.google.com/web/tools/puppeteer/troubleshooting - - // These links might be worth looking at in future if diagnosing other issues: - // https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-on-alpine - // https://github.com/puppeteer/puppeteer/issues/1825 - // const chromeFlags = [ - // '--headless', - // '--no-sandbox', - // "--disable-gpu", - // "--single-process", - // "--no-zygote" - // ] - // */ - // } - // else - // { - // // #if (DEBUG) - // // log.LogInformation($"DBG: ReportBiz::calling browserfetcher"); - // // #endif - // log.LogDebug($"Windows: Calling browserFetcher download async now:"); - // await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultChromiumRevision); - // } - - // //Set Chromium args - // //*** DANGER: --disable-dev-shm-usage will crash linux ayanova when it runs out of memory **** - // //that was only suitable for dockerized scenario as it had an alt swap system - // //var OriginalDefaultArgs = "--disable-dev-shm-usage --single-process --no-sandbox --disable-gpu --no-zygote "; - // var DefaultArgs = "--headless --no-sandbox"; - // if (!string.IsNullOrWhiteSpace(ServerBootConfig.AYANOVA_REPORT_RENDER_BROWSER_PARAMS)) - // { - // log.LogDebug($"AYANOVA_REPORT_RENDER_BROWSER_PARAMS will be used: {ServerBootConfig.AYANOVA_REPORT_RENDER_BROWSER_PARAMS}"); - // lo.Args = new string[] { $"{ServerBootConfig.AYANOVA_REPORT_RENDER_BROWSER_PARAMS}" };// AYANOVA_REPORT_RENDER_BROWSER_PARAMS - // } - // else - // { - // log.LogDebug($"AYANOVA_REPORT_RENDER_BROWSER_PARAMS not set, using defaults '{DefaultArgs}'"); - // lo.Args = new string[] { DefaultArgs }; - // } - // System.Text.StringBuilder PageLog = new System.Text.StringBuilder(); - - // if (DateTime.UtcNow > renderTimeOutExpiry) - // throw new ReportRenderTimeOutException(); - - // //API DOCS http://www.puppeteersharp.com/api/index.html - // log.LogDebug($"Launching headless Browser and new page now:"); - // using (var browser = await Puppeteer.LaunchAsync(lo)) - // using (var page = (await browser.PagesAsync())[0]) - // // using (var page = await browser.NewPageAsync()) - // { - // //track this process for timeout purposes - // ReportRenderManager.SetProcess(browser.Process.Id, renderTimeOutExpiry, log); - // page.DefaultTimeout = 0;//infinite timeout as we are controlling how long the process can live for with the reportprocessmanager - // try - // { - // //info and error logging - // page.Console += async (sender, args) => - // { - // switch (args.Message.Type) - // { - // case ConsoleType.Error: - // try - // { - // var errorArgs = await Task.WhenAll(args.Message.Args.Select(arg => arg.ExecutionContext.EvaluateFunctionAsync("(arg) => arg instanceof Error ? arg.message : arg", arg))); - // PageLog.AppendLine($"ERROR: {args.Message.Text} args: [{string.Join(", ", errorArgs)}]"); - // } - // catch { } - // break; - // case ConsoleType.Warning: - // PageLog.AppendLine($"WARNING: {args.Message.Text}"); - // break; - // default: - // PageLog.AppendLine($"INFO: {args.Message.Text}"); - - - // break; - // } - // }; - - // log.LogDebug($"Preparing page: adding base reporting scripts to page"); - // if (DateTime.UtcNow > renderTimeOutExpiry) - // throw new ReportRenderTimeOutException(); - - // //Add Handlebars JS for compiling and presenting - // //https://handlebarsjs.com/ - // await page.AddScriptTagAsync(new AddTagOptions() { Path = Path.Combine(ReportJSFolderPath, "ay-hb.js") }); - - // //add Marked for markdown processing - // //https://github.com/markedjs/marked - // await page.AddScriptTagAsync(new AddTagOptions() { Path = Path.Combine(ReportJSFolderPath, "ay-md.js") }); - - // //add DOM Purify for markdown template sanitization processing - // //https://github.com/cure53/DOMPurify - // await page.AddScriptTagAsync(new AddTagOptions() { Path = Path.Combine(ReportJSFolderPath, "ay-pf.js") }); - - // //add Bar code library if our bar code helper is referenced - // //https://github.com/metafloor/bwip-js - // if (report.Template.Contains("ayBC ") || report.JsHelpers.Contains("ayBC ")) - // await page.AddScriptTagAsync(new AddTagOptions() { Path = Path.Combine(ReportJSFolderPath, "ay-bc.js") }); - - // //add stock helpers - // await page.AddScriptTagAsync(new AddTagOptions() { Path = Path.Combine(ReportJSFolderPath, "ay-report.js") }); - - // //execute to add to handlebars - // await page.EvaluateExpressionAsync("ayRegisterHelpers();"); - // if (DateTime.UtcNow > renderTimeOutExpiry) - // throw new ReportRenderTimeOutException(); - // log.LogDebug($"Preparing page: adding this report's scripts, style and templates to page"); - - // //add report pre-render, helpers and style - // if (string.IsNullOrWhiteSpace(report.JsPrerender)) - // { - // report.JsPrerender = "async function ayPrepareData(reportData){return reportData;}"; - // } - // await page.AddScriptTagAsync(new AddTagOptions() { Content = report.JsPrerender }); - - // if (!string.IsNullOrWhiteSpace(report.JsHelpers)) - // await page.AddScriptTagAsync(new AddTagOptions() { Content = report.JsHelpers }); - - // if (!string.IsNullOrWhiteSpace(report.Style)) - // await page.AddStyleTagAsync(new AddTagOptions() { Content = report.Style }); - - // log.LogDebug($"Preparing page: adding Client meta data"); - - // //Client meta data to JSON string - // var clientMeta = reportRequest.ClientMeta.ToString(); - - // log.LogDebug($"Preparing page: adding Server meta data"); - // //Server meta data - // var logo = await ct.Logo.AsNoTracking().SingleOrDefaultAsync(); - - // var HasSmallLogo = "false"; - // var HasMediumLogo = "false"; - // var HasLargeLogo = "false"; - // if (logo != null) - // { - // if (logo.Small != null) HasSmallLogo = "true"; - // if (logo.Medium != null) HasMediumLogo = "true"; - // if (logo.Large != null) HasLargeLogo = "true"; - // } - // var HasPostalAddress = !string.IsNullOrWhiteSpace(ServerGlobalBizSettings.Cache.PostAddress) ? "true" : "false"; - // var HasStreetAddress = !string.IsNullOrWhiteSpace(ServerGlobalBizSettings.Cache.Address) ? "true" : "false"; - // var serverMeta = $"{{ayApiUrl:`{apiUrl}`, HasSmallLogo:{HasSmallLogo}, HasMediumLogo:{HasMediumLogo}, HasLargeLogo:{HasLargeLogo},CompanyName: `{AyaNova.Core.License.ActiveKey.RegisteredTo}`,CompanyWebAddress:`{ServerGlobalBizSettings.Cache.WebAddress}`,CompanyEmailAddress:`{ServerGlobalBizSettings.Cache.EmailAddress}`,CompanyPhone1:`{ServerGlobalBizSettings.Cache.Phone1}`,CompanyPhone2:`{ServerGlobalBizSettings.Cache.Phone2}`,HasPostalAddress:{HasPostalAddress},CompanyPostAddress:`{ServerGlobalBizSettings.Cache.PostAddress}`,CompanyPostCity:`{ServerGlobalBizSettings.Cache.PostCity}`,CompanyPostRegion:`{ServerGlobalBizSettings.Cache.PostRegion}`,CompanyPostCountry:`{ServerGlobalBizSettings.Cache.PostCountry}`,CompanyPostCode:`{ServerGlobalBizSettings.Cache.PostCode}`,HasStreetAddress:{HasStreetAddress},CompanyAddress:`{ServerGlobalBizSettings.Cache.Address}`,CompanyCity:`{ServerGlobalBizSettings.Cache.City}`,CompanyRegion:`{ServerGlobalBizSettings.Cache.Region}`,CompanyCountry:`{ServerGlobalBizSettings.Cache.Country}`,CompanyLatitude:{ServerGlobalBizSettings.Cache.Latitude},CompanyLongitude:{ServerGlobalBizSettings.Cache.Longitude}}}"; - - // log.LogDebug($"Preparing page: adding Report meta data"); - - // //Custom fields definition for report usage - // string CustomFieldsTemplate = "null"; - // var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == report.AType.ToString()); - // if (FormCustomization != null) - // { - // CustomFieldsTemplate = FormCustomization.Template; - // } - - // //Report meta data - // var reportMeta = $"{{Id:{report.Id},Name:`{report.Name}`,Notes:`{report.Notes}`,AType:`{report.AType}`,CustomFieldsDefinition:{CustomFieldsTemplate},DataListKey:`{reportRequest.DataListKey}`,SelectedRowIds: `{string.Join(",", reportRequest.SelectedRowIds)}`}}"; - - - // //duplicate meta data in report page wide variable for use by our internal functions - // await page.AddScriptTagAsync(new AddTagOptions() { Content = $"var AYMETA={{ ayReportMetaData:{reportMeta}, ayClientMetaData:{clientMeta}, ayServerMetaData:{serverMeta} }}" }); - - // if (DateTime.UtcNow > renderTimeOutExpiry) - // throw new ReportRenderTimeOutException(); - - - // //#### DEBUGGING TOOL: view page contents - // // var pagecontent = await page.GetContentAsync(); - - // //prePareData / preRender - // var ReportDataObject = $"{{ ayReportData:{ReportData}, ayReportMetaData:{reportMeta}, ayClientMetaData:{clientMeta}, ayServerMetaData:{serverMeta} }}"; - - // log.LogDebug($"PageLog before render:{PageLog.ToString()}"); - // log.LogDebug($"Calling ayPreRender..."); - // await page.WaitForExpressionAsync($"ayPreRender({ReportDataObject})"); - // log.LogDebug($"ayPreRender completed"); - - // if (DateTime.UtcNow > renderTimeOutExpiry) - // throw new ReportRenderTimeOutException(); - // //compile the template - // log.LogDebug($"Calling Handlebars.compile..."); - - // var compileScript = $"Handlebars.compile(`{report.Template}`)(PreParedReportDataObject);"; - // if (DateTime.UtcNow > renderTimeOutExpiry) - // throw new ReportRenderTimeOutException(); - // var compiledHTML = await page.EvaluateExpressionAsync(compileScript); - // if (DateTime.UtcNow > renderTimeOutExpiry) - // throw new ReportRenderTimeOutException(); - // //render report as HTML - // log.LogDebug($"Setting page content to compiled HTML"); - - // await page.SetContentAsync(compiledHTML); - - // //add style (after page or it won't work) - // if (!string.IsNullOrWhiteSpace(report.Style)) - // { - // log.LogDebug($"Adding report template Style CSS"); - // await page.AddStyleTagAsync(new AddTagOptions { Content = report.Style }); - // } - - // string outputFileName = StringUtil.ReplaceLastOccurrence(FileUtil.NewRandomFileName, ".", "") + ".pdf"; - // string outputFullPath = System.IO.Path.Combine(FileUtil.TemporaryFilesFolder, outputFileName); - - - // //Set PDF options - // //https://pptr.dev/#?product=Puppeteer&version=v5.3.0&show=api-pagepdfoptions - // log.LogDebug($"Resolving PDF Options from report settings"); - - // var PdfOptions = new PdfOptions() { }; - - // PdfOptions.DisplayHeaderFooter = report.DisplayHeaderFooter; - // if (report.DisplayHeaderFooter) - // { - // var ClientPDFDate = reportRequest.ClientMeta["PDFDate"].Value(); - // var ClientPDFTime = reportRequest.ClientMeta["PDFTime"].Value(); - // PdfOptions.HeaderTemplate = report.HeaderTemplate.Replace("PDFDate", ClientPDFDate).Replace("PDFTime", ClientPDFTime); - // PdfOptions.FooterTemplate = report.FooterTemplate.Replace("PDFDate", ClientPDFDate).Replace("PDFTime", ClientPDFTime); - - // } - - // if (report.PaperFormat != ReportPaperFormat.NotSet) - // { - // switch (report.PaperFormat) - // { - // case ReportPaperFormat.A0: - // PdfOptions.Format = PuppeteerSharp.Media.PaperFormat.A0; - // break; - // case ReportPaperFormat.A1: - // PdfOptions.Format = PuppeteerSharp.Media.PaperFormat.A1; - // break; - // case ReportPaperFormat.A2: - // PdfOptions.Format = PuppeteerSharp.Media.PaperFormat.A2; - // break; - // case ReportPaperFormat.A3: - // PdfOptions.Format = PuppeteerSharp.Media.PaperFormat.A3; - // break; - // case ReportPaperFormat.A4: - // PdfOptions.Format = PuppeteerSharp.Media.PaperFormat.A4; - // break; - // case ReportPaperFormat.A5: - // PdfOptions.Format = PuppeteerSharp.Media.PaperFormat.A5; - // break; - // case ReportPaperFormat.A6: - // PdfOptions.Format = PuppeteerSharp.Media.PaperFormat.A6; - // break; - // case ReportPaperFormat.Ledger: - // PdfOptions.Format = PuppeteerSharp.Media.PaperFormat.Ledger; - // break; - // case ReportPaperFormat.Legal: - // PdfOptions.Format = PuppeteerSharp.Media.PaperFormat.Legal; - // break; - // case ReportPaperFormat.Letter: - // PdfOptions.Format = PuppeteerSharp.Media.PaperFormat.Letter; - // break; - // case ReportPaperFormat.Tabloid: - // PdfOptions.Format = PuppeteerSharp.Media.PaperFormat.Tabloid; - // break; - // } - // } - - // PdfOptions.Landscape = report.Landscape; - // if (!string.IsNullOrWhiteSpace(report.MarginOptionsBottom)) - // PdfOptions.MarginOptions.Bottom = report.MarginOptionsBottom; - - // if (!string.IsNullOrWhiteSpace(report.MarginOptionsLeft)) - // PdfOptions.MarginOptions.Left = report.MarginOptionsLeft; - - // if (!string.IsNullOrWhiteSpace(report.MarginOptionsRight)) - // PdfOptions.MarginOptions.Right = report.MarginOptionsRight; - - // if (!string.IsNullOrWhiteSpace(report.MarginOptionsTop)) - // PdfOptions.MarginOptions.Top = report.MarginOptionsTop; - - // //holding this back until figure it out - // //it's not really a report property, but a print time / render property - // //PdfOptions.PageRanges=report.PageRanges; - - // PdfOptions.PreferCSSPageSize = report.PreferCSSPageSize; - // PdfOptions.PrintBackground = report.PrintBackground; - // //Defaults to 1. Scale amount must be between 0.1 and 2. - // PdfOptions.Scale = report.Scale; - // if (DateTime.UtcNow > renderTimeOutExpiry) - // throw new ReportRenderTimeOutException(); - // //render to pdf and return - // log.LogDebug($"Calling render page contents to PDF"); - // await page.PdfAsync(outputFullPath, PdfOptions);//###### TODO: SLOW NEEDS TIMEOUT HERE ONCE SUPPORTED, open bug: https://github.com/hardkoded/puppeteer-sharp/issues/1710 - - // log.LogDebug($"Closing Page"); - // await page.CloseAsync(); - // log.LogDebug($"Closing Browser"); - // await browser.CloseAsync(); - - // log.LogDebug($"Render completed, returning results"); - // return outputFileName; - // } - // catch (ReportRenderTimeOutException) - // { - // log.LogDebug("Caught ReportRendertimeOutException, re-throwing"); - // throw; - // } - // catch (PuppeteerSharp.TargetClosedException) - // { - // log.LogDebug("Caught PuppeteerSharp.TargetClosedException throwing as ReportRendertimeOutException (timed out and closed from process sweeper)"); - // //we closed it because the timeout hit and the CoreJobReportRenderEngineProcessCleanup job cleaned it out - // //so return the error the client expects in this scenario - // throw new ReportRenderTimeOutException(); - // } - // catch (Exception ex) - // { - // log.LogDebug(ex, $"Error during report rendering"); - // //This is the error when a helper is used on the template but doesn't exist: - // //Evaluation failed: d - // //(it might also mean other things wrong with template) - // if (PageLog.Length > 0) - // { - // log.LogInformation($"Exception caught while rendering report \"{report.Name}\", report Page console log:"); - // log.LogInformation(PageLog.ToString()); - // } - - // // var v=await page.GetContentAsync();//for debugging purposes - // throw; - // } - // finally - // { - // log.LogDebug($"reached finally block"); - // if (!page.IsClosed) - // { - // log.LogDebug($"Page not closed in finally block, closing now"); - // await page.CloseAsync(); - // } - // if (!browser.IsClosed) - // { - // log.LogDebug($"Browser not closed in finally block, closing now"); - // await browser.CloseAsync(); - // } - // log.LogDebug($"Calling ReportRenderManager.RemoveProcess to stop tracking this process"); - // ReportRenderManager.RemoveProcess(browser.Process.Id, log); - // } - // } - // } - - - - //////////////////////////////////////////////////////////////////////////////////////////////// //RENDER // @@ -825,17 +400,10 @@ namespace AyaNova.Biz //includeWoItemDescendants? reportRequest.IncludeWoItemDescendants = report.IncludeWoItemDescendants; - - - //Do we need to rehydrate the ID List from a DataList? if (reportRequest.SelectedRowIds.Length == 0) reportRequest.SelectedRowIds = await DataListSelectedProcessingOptions.RehydrateIdList(reportRequest, ct, effectiveRoles, log, UserId, UserTranslationId); - - //todo: put in job add job handler to do the remainder of this request - - var JobName = $"LT:Report id: \"{reportRequest.ReportId}\" LT:{reportRequest.AType} ({reportRequest.SelectedRowIds.LongLength}) LT:User {userName}"; JObject o = JObject.FromObject(new { @@ -866,8 +434,8 @@ namespace AyaNova.Biz var log = AyaNova.Util.ApplicationLogging.CreateLogger("ReportBiz::DoRenderJob"); await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Running); - var renderTimeOutExpiry = DateTime.UtcNow.AddMinutes(ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT); - ReportRenderManager.AddJob(job.GId, renderTimeOutExpiry, log); + + ReportRenderManager.AddJob(job.GId, log); // await JobsBiz.LogJobAsync(job.GId, $"LT:StartJob {job.JobType}"); //rehydrate job objects @@ -887,15 +455,15 @@ namespace AyaNova.Biz await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Failed); return; } - if (!ReportRenderManager.KeepGoing(job.GId)) - { return; - } //Get data log.LogDebug("Getting report data now"); - var ReportData = await GetReportData(reportRequest, renderTimeOutExpiry, RequestIsCustomerWorkOrderReport); + var ReportData = await GetReportData(reportRequest, job.GId, RequestIsCustomerWorkOrderReport); + //THIS is here to catch scenario where report data returned null because it expired, not because of an issue + if (!ReportRenderManager.KeepGoing(job.GId)) + return; //if GetReportData errored then will return null so need to return that as well here if (ReportData == null) { @@ -905,15 +473,8 @@ namespace AyaNova.Biz } if (!ReportRenderManager.KeepGoing(job.GId)) - { return; - } - if (DateTime.UtcNow > renderTimeOutExpiry) - { - await HandleTimeOut(job, log, reportRequest, userName); - return; - } //initialization log.LogDebug("Initializing report rendering system"); bool AutoDownloadChromium = true; @@ -976,12 +537,8 @@ namespace AyaNova.Biz } System.Text.StringBuilder PageLog = new System.Text.StringBuilder(); - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); if (!ReportRenderManager.KeepGoing(job.GId)) - { return; - } //API DOCS http://www.puppeteersharp.com/api/index.html log.LogDebug($"Launching headless Browser and new page now:"); @@ -1020,12 +577,8 @@ namespace AyaNova.Biz }; log.LogDebug($"Preparing page: adding base reporting scripts to page"); - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); if (!ReportRenderManager.KeepGoing(job.GId)) - { return; - } //Add Handlebars JS for compiling and presenting //https://handlebarsjs.com/ @@ -1049,12 +602,8 @@ namespace AyaNova.Biz //execute to add to handlebars await page.EvaluateExpressionAsync("ayRegisterHelpers();"); - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); if (!ReportRenderManager.KeepGoing(job.GId)) - { return; - } log.LogDebug($"Preparing page: adding this report's scripts, style and templates to page"); //add report pre-render, helpers and style @@ -1109,12 +658,8 @@ namespace AyaNova.Biz //duplicate meta data in report page wide variable for use by our internal functions await page.AddScriptTagAsync(new AddTagOptions() { Content = $"var AYMETA={{ ayReportMetaData:{reportMeta}, ayClientMetaData:{clientMeta}, ayServerMetaData:{serverMeta} }}" }); - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); if (!ReportRenderManager.KeepGoing(job.GId)) - { return; - } //#### DEBUGGING TOOL: view page contents // var pagecontent = await page.GetContentAsync(); @@ -1127,27 +672,17 @@ namespace AyaNova.Biz await page.WaitForExpressionAsync($"ayPreRender({ReportDataObject})"); log.LogDebug($"ayPreRender completed"); - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); if (!ReportRenderManager.KeepGoing(job.GId)) - { return; - } //compile the template log.LogDebug($"Calling Handlebars.compile..."); var compileScript = $"Handlebars.compile(`{report.Template}`)(PreParedReportDataObject);"; - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); - if(!ReportRenderManager.KeepGoing(job.GId)){ - return; - } + if (!ReportRenderManager.KeepGoing(job.GId)) + return; var compiledHTML = await page.EvaluateExpressionAsync(compileScript); - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); - if(!ReportRenderManager.KeepGoing(job.GId)){ - return; - } + if (!ReportRenderManager.KeepGoing(job.GId)) + return; //render report as HTML log.LogDebug($"Setting page content to compiled HTML"); @@ -1241,11 +776,8 @@ namespace AyaNova.Biz PdfOptions.PrintBackground = report.PrintBackground; //Defaults to 1. Scale amount must be between 0.1 and 2. PdfOptions.Scale = report.Scale; - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); - if(!ReportRenderManager.KeepGoing(job.GId)){ - return; - } + if (!ReportRenderManager.KeepGoing(job.GId)) + return; //render to pdf and return log.LogDebug($"Calling render page contents to PDF"); await page.PdfAsync(outputFullPath, PdfOptions);//###### TODO: SLOW NEEDS TIMEOUT HERE ONCE SUPPORTED, open bug: https://github.com/hardkoded/puppeteer-sharp/issues/1710 diff --git a/server/AyaNova/biz/ReviewBiz.cs b/server/AyaNova/biz/ReviewBiz.cs index d3f447e6..c687071e 100644 --- a/server/AyaNova/biz/ReviewBiz.cs +++ b/server/AyaNova/biz/ReviewBiz.cs @@ -335,7 +335,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -349,8 +349,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (Review w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -380,11 +379,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } public async Task> ImportData(JArray ja) diff --git a/server/AyaNova/biz/ServiceBankBiz.cs b/server/AyaNova/biz/ServiceBankBiz.cs index ab2f750e..38dd6064 100644 --- a/server/AyaNova/biz/ServiceBankBiz.cs +++ b/server/AyaNova/biz/ServiceBankBiz.cs @@ -264,7 +264,7 @@ // //////////////////////////////////////////////////////////////////////////////////////////////// // //REPORTING // // -// public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) +// public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) // { // JArray ReportData = new JArray(); // while (idList.Any()) @@ -293,11 +293,11 @@ // // IMPORT EXPORT // // -// public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) +// public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) // { // //for now just re-use the report data code // //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time -// return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); +// return await GetReportData(dataListSelectedRequest, jobId); // } diff --git a/server/AyaNova/biz/ServiceRateBiz.cs b/server/AyaNova/biz/ServiceRateBiz.cs index 996f22c5..c159c66e 100644 --- a/server/AyaNova/biz/ServiceRateBiz.cs +++ b/server/AyaNova/biz/ServiceRateBiz.cs @@ -302,7 +302,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -316,8 +316,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (ServiceRate w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) jo["CustomFields"] = JObject.Parse((string)jo["CustomFields"]); @@ -333,11 +332,11 @@ namespace AyaNova.Biz // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/TaskGroupBiz.cs b/server/AyaNova/biz/TaskGroupBiz.cs index 12af7412..127bd4e2 100644 --- a/server/AyaNova/biz/TaskGroupBiz.cs +++ b/server/AyaNova/biz/TaskGroupBiz.cs @@ -286,7 +286,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -300,8 +300,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (TaskGroup w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) jo["CustomFields"] = JObject.Parse((string)jo["CustomFields"]); @@ -317,11 +316,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } public async Task> ImportData(JArray ja) diff --git a/server/AyaNova/biz/TaxCodeBiz.cs b/server/AyaNova/biz/TaxCodeBiz.cs index 8b78f8c3..68e7a4ce 100644 --- a/server/AyaNova/biz/TaxCodeBiz.cs +++ b/server/AyaNova/biz/TaxCodeBiz.cs @@ -331,7 +331,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -345,8 +345,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (TaxCode w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) jo["CustomFields"] = JObject.Parse((string)jo["CustomFields"]); @@ -362,11 +361,11 @@ namespace AyaNova.Biz // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/TravelRateBiz.cs b/server/AyaNova/biz/TravelRateBiz.cs index d5f71675..0b22e896 100644 --- a/server/AyaNova/biz/TravelRateBiz.cs +++ b/server/AyaNova/biz/TravelRateBiz.cs @@ -298,7 +298,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -312,8 +312,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (TravelRate w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) jo["CustomFields"] = JObject.Parse((string)jo["CustomFields"]); @@ -329,11 +328,11 @@ namespace AyaNova.Biz // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/UnitBiz.cs b/server/AyaNova/biz/UnitBiz.cs index 33a19f20..c79361d0 100644 --- a/server/AyaNova/biz/UnitBiz.cs +++ b/server/AyaNova/biz/UnitBiz.cs @@ -293,7 +293,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -307,8 +307,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (Unit w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -381,11 +380,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/UnitMeterReadingBiz.cs b/server/AyaNova/biz/UnitMeterReadingBiz.cs index f84865cb..e38c8252 100644 --- a/server/AyaNova/biz/UnitMeterReadingBiz.cs +++ b/server/AyaNova/biz/UnitMeterReadingBiz.cs @@ -142,7 +142,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -156,8 +156,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (UnitMeterReading w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w); var jo = JObject.FromObject(w); ReportData.Add(jo); @@ -180,11 +179,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/UnitModelBiz.cs b/server/AyaNova/biz/UnitModelBiz.cs index 9b3f1f81..697e7dcb 100644 --- a/server/AyaNova/biz/UnitModelBiz.cs +++ b/server/AyaNova/biz/UnitModelBiz.cs @@ -276,7 +276,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -290,8 +290,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (UnitModel w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -313,11 +312,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } public async Task> ImportData(JArray ja) diff --git a/server/AyaNova/biz/UserBiz.cs b/server/AyaNova/biz/UserBiz.cs index 76d2a963..38f441dd 100644 --- a/server/AyaNova/biz/UserBiz.cs +++ b/server/AyaNova/biz/UserBiz.cs @@ -1022,7 +1022,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -1045,8 +1045,7 @@ namespace AyaNova.Biz //foreach (User w in orderedList) foreach (var w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; await PopulateVizFields(w, UserTypesEnumList); var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) @@ -1081,11 +1080,11 @@ namespace AyaNova.Biz // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/VendorBiz.cs b/server/AyaNova/biz/VendorBiz.cs index f2b88139..60a61bfb 100644 --- a/server/AyaNova/biz/VendorBiz.cs +++ b/server/AyaNova/biz/VendorBiz.cs @@ -315,7 +315,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -329,8 +329,7 @@ namespace AyaNova.Biz var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (Vendor w in orderedList) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) jo["CustomFields"] = JObject.Parse((string)jo["CustomFields"]); @@ -346,11 +345,11 @@ namespace AyaNova.Biz // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index 03a080e1..3862234c 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -938,7 +938,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { // #if (DEBUG) // var watch = System.Diagnostics.Stopwatch.StartNew(); @@ -952,20 +952,19 @@ namespace AyaNova.Biz while (idList.Any()) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; var batch = idList.Take(IReportAbleObject.REPORT_DATA_BATCH_SIZE); idList = idList.Skip(IReportAbleObject.REPORT_DATA_BATCH_SIZE).ToArray(); List batchResults = new List(); foreach (long batchId in batch) + { + if (!ReportRenderManager.KeepGoing(jobId)) return null; batchResults.Add(await WorkOrderGetPartialAsync(dataListSelectedRequest.AType, batchId, dataListSelectedRequest.IncludeWoItemDescendants, true)); + } foreach (WorkOrder w in batchResults) { - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); - if (DateTime.UtcNow > renderTimeOutExpiry) - throw new ReportRenderTimeOutException(); + if (!ReportRenderManager.KeepGoing(jobId)) return null; var jo = JObject.FromObject(w); //WorkOrder header custom fields @@ -1114,11 +1113,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, Guid jobId) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time - return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); + return await GetReportData(dataListSelectedRequest, jobId); } //////////////////////////////////////////////////////////////////////////////////////////////// @@ -3275,7 +3274,7 @@ namespace AyaNova.Biz Tax = (TaxCode)oc.Get("tax", o.TaxCodeId); } - + if (Tax != null) o.TaxCodeViz = Tax.Name; diff --git a/server/AyaNova/generator/CoreJobBackup.cs b/server/AyaNova/generator/CoreJobBackup.cs index 217f7237..efc96d08 100644 --- a/server/AyaNova/generator/CoreJobBackup.cs +++ b/server/AyaNova/generator/CoreJobBackup.cs @@ -29,7 +29,7 @@ namespace AyaNova.Biz if (BackupIsRunning) return; if (!OnDemand) { - log.LogDebug("Checking if backup should run"); + log.LogTrace("Checking if backup should run"); if (!ServerGlobalOpsSettingsCache.Backup.Active) { log.LogDebug("Automatic backup is set to INACTIVE - not backing up"); @@ -38,7 +38,7 @@ namespace AyaNova.Biz if (DateTime.UtcNow < ServerGlobalOpsSettingsCache.NextBackup) { - log.LogDebug("Not past backup time yet"); + log.LogTrace("Not past backup time yet"); return; } } diff --git a/server/AyaNova/generator/CoreJobLicense.cs b/server/AyaNova/generator/CoreJobLicense.cs index 81fb6487..efb27879 100644 --- a/server/AyaNova/generator/CoreJobLicense.cs +++ b/server/AyaNova/generator/CoreJobLicense.cs @@ -33,7 +33,7 @@ namespace AyaNova.Biz // public static async Task DoWorkAsync() { - log.LogDebug("Job starting"); + log.LogTrace("Job starting"); var tsSinceLastCheck = DateTime.UtcNow - _lastCheck; //which track are we on? /* @@ -56,10 +56,10 @@ namespace AyaNova.Biz tsCheckFrequency = SLOW_TRACK; break; } - log.LogDebug($"Check frequency{tsCheckFrequency}"); + log.LogTrace($"Check frequency{tsCheckFrequency}"); if (tsSinceLastCheck < tsCheckFrequency) { - log.LogDebug($"Not yet"); + log.LogTrace($"Not yet"); return; } diff --git a/server/AyaNova/generator/CoreJobNotify.cs b/server/AyaNova/generator/CoreJobNotify.cs index a76d8e7a..69d61d34 100644 --- a/server/AyaNova/generator/CoreJobNotify.cs +++ b/server/AyaNova/generator/CoreJobNotify.cs @@ -34,16 +34,16 @@ namespace AyaNova.Biz // public static async Task DoWorkAsync() { - log.LogDebug("Checking if Notify should run"); + log.LogTrace("Checking if Notify should run"); if (NotifyIsRunning) { - log.LogDebug("Notify is running already exiting this cycle"); + log.LogTrace("Notify is running already exiting this cycle"); return; } //This will get triggered roughly every minute, but we don't want to deliver that frequently if (DateTime.UtcNow - lastRun < RUN_EVERY_INTERVAL) { - log.LogDebug($"Notify ran less than {RUN_EVERY_INTERVAL} ago, exiting this cycle"); + log.LogTrace($"Notify ran less than {RUN_EVERY_INTERVAL} ago, exiting this cycle"); return; } try diff --git a/server/AyaNova/generator/CoreJobPMGenerate.cs b/server/AyaNova/generator/CoreJobPMGenerate.cs index f530a372..83d2e154 100644 --- a/server/AyaNova/generator/CoreJobPMGenerate.cs +++ b/server/AyaNova/generator/CoreJobPMGenerate.cs @@ -31,16 +31,16 @@ namespace AyaNova.Biz public static async Task DoWorkAsync() { - log.LogDebug("Checking if PMGenerate should run"); + log.LogTrace("Checking if PMGenerate should run"); if (IsRunning) { - log.LogDebug("PMGenerate is running already exiting this cycle"); + log.LogTrace("PMGenerate is running already exiting this cycle"); return; } //This will get triggered roughly every minute, but we don't want to deliver that frequently if (DateTime.UtcNow - lastRun < RUN_EVERY_INTERVAL) { - log.LogDebug($"PMGenerate ran less than {RUN_EVERY_INTERVAL} ago, exiting this cycle"); + log.LogTrace($"PMGenerate ran less than {RUN_EVERY_INTERVAL} ago, exiting this cycle"); return; } try diff --git a/server/AyaNova/generator/CoreJobPMInventoryCheck.cs b/server/AyaNova/generator/CoreJobPMInventoryCheck.cs index 7e9c1eb2..a949224b 100644 --- a/server/AyaNova/generator/CoreJobPMInventoryCheck.cs +++ b/server/AyaNova/generator/CoreJobPMInventoryCheck.cs @@ -31,16 +31,16 @@ namespace AyaNova.Biz public static async Task DoWorkAsync() { - log.LogDebug("Checking if CoreJobPMInventoryCheck should run"); + log.LogTrace("Checking if CoreJobPMInventoryCheck should run"); if (IsRunning) { - log.LogDebug("CoreJobPMInventoryCheck is running already exiting this cycle"); + log.LogTrace("CoreJobPMInventoryCheck is running already exiting this cycle"); return; } //This will get triggered roughly every minute, but we don't want to deliver that frequently if (DateTime.UtcNow - lastRun < RUN_EVERY_INTERVAL) { - log.LogDebug($"CoreJobPMInventoryCheck ran less than {RUN_EVERY_INTERVAL} ago, exiting this cycle"); + log.LogTrace($"CoreJobPMInventoryCheck ran less than {RUN_EVERY_INTERVAL} ago, exiting this cycle"); return; } diff --git a/server/AyaNova/generator/CoreJobReportRenderEngineProcessCleanup.cs b/server/AyaNova/generator/CoreJobReportRenderEngineProcessCleanup.cs index 611bf0ce..5b49a615 100644 --- a/server/AyaNova/generator/CoreJobReportRenderEngineProcessCleanup.cs +++ b/server/AyaNova/generator/CoreJobReportRenderEngineProcessCleanup.cs @@ -14,7 +14,7 @@ namespace AyaNova.Biz private static DateTime _lastRun = DateTime.UtcNow; //SET LOW INTENTIONALLY AS CAN EAT UP A LOT OF RESOURCES QUICKLY IF RUN'S PAST TIME - private static TimeSpan tsRunEvery = new TimeSpan(0, 1, 1);//every this minutes run the cleanup task + private static TimeSpan tsRunEvery = new TimeSpan(0, 0, 20);//every twenty seconds run the cleanup task //////////////////////////////////////////////////////////////////////////////////////////////// // @@ -23,9 +23,8 @@ namespace AyaNova.Biz { if (DateUtil.IsAfterDuration(_lastRun, tsRunEvery)) { - log.LogDebug("Checking for expired processes"); + log.LogTrace("Checking for expired report jobs"); await Util.ReportRenderManager.KillExpiredRenders(log); - //FileUtil.CleanTemporaryFilesFolder(new TimeSpan(0,5,0));//erase any files found to be older than 5 minutes var now = DateTime.UtcNow; _lastRun = now; } diff --git a/server/AyaNova/generator/CoreJobSweeper.cs b/server/AyaNova/generator/CoreJobSweeper.cs index 4e7cab28..9f950e70 100644 --- a/server/AyaNova/generator/CoreJobSweeper.cs +++ b/server/AyaNova/generator/CoreJobSweeper.cs @@ -17,7 +17,7 @@ namespace AyaNova.Biz { private static ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("CoreJobSweeper"); private static DateTime lastSweep = DateTime.MinValue; - private static TimeSpan SWEEP_EVERY_INTERVAL = new TimeSpan(0, 0, 10); + private static TimeSpan SWEEP_EVERY_INTERVAL = new TimeSpan(0, 10, 10);//every ten minutes roughly private static TimeSpan SUCCEEDED_JOBS_DELETE_AFTER_THIS_TIMESPAN = new TimeSpan(14, 0, 0, 0);//14 days private static TimeSpan FAILED_JOBS_DELETE_AFTER_THIS_TIMESPAN = new TimeSpan(14, 0, 0, 0);//14 days (gives people time to notice and look into it) private static TimeSpan INTERNAL_JOBS_LOGS_DELETE_AFTER_THIS_TIMESPAN = new TimeSpan(14, 0, 0, 0);//14 days diff --git a/server/AyaNova/util/ReportProcessManager.cs b/server/AyaNova/util/ReportProcessManager.cs index e6305baf..580d862a 100644 --- a/server/AyaNova/util/ReportProcessManager.cs +++ b/server/AyaNova/util/ReportProcessManager.cs @@ -107,10 +107,10 @@ namespace AyaNova.Util } - internal static void AddJob(Guid jobId, DateTime expires, ILogger log) + internal static void AddJob(Guid jobId, ILogger log) { log.LogDebug($"AddJob - {jobId} to the collection"); - _baginstances.Add(new ReportRenderInstanceInfo(jobId, expires)); + _baginstances.Add(new ReportRenderInstanceInfo(jobId, DateTime.UtcNow.AddMinutes(ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT))); log.LogInformation($"AddJob - there are currently {_baginstances.Count} instances in the collection"); } @@ -144,6 +144,8 @@ namespace AyaNova.Util internal static bool KeepGoing(Guid jobId) { + //if job id is empty it means it was called from outside of a job (report designer get data for example) + if(jobId==Guid.Empty) return true; foreach (var i in _baginstances) { if (i.JobId == jobId)