diff --git a/server/AyaNova/Controllers/ReportController.cs b/server/AyaNova/Controllers/ReportController.cs index 93a635f0..a5f0b0ab 100644 --- a/server/AyaNova/Controllers/ReportController.cs +++ b/server/AyaNova/Controllers/ReportController.cs @@ -175,12 +175,20 @@ namespace AyaNova.Api.Controllers //cap the data returned selectedRequest.ReportDesignerSample = true; - - var reportData = await biz.GetReportData(selectedRequest); - if (reportData == null) - return BadRequest(new ApiErrorResponse(biz.Errors)); - else - return Ok(ApiOkResponse.Response(reportData)); + JArray reportData; + try + { + reportData = await biz.GetReportData(selectedRequest, DateTime.UtcNow.AddMinutes(ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT)); + if (reportData == null) + return BadRequest(new ApiErrorResponse(biz.Errors)); + else + return Ok(ApiOkResponse.Response(reportData)); + } + catch (ReportRenderTimeOutException) + { + log.LogInformation($"GetReportData timeout data list key: {selectedRequest.DataListKey}, record count:{selectedRequest.SelectedRowIds.LongLength}, user:{UserNameFromContext.Name(HttpContext.Items)} "); + return Ok(ApiOkResponse.Response(new { timeout = true, timeoutconfig = ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT })); + } } @@ -209,14 +217,17 @@ namespace AyaNova.Api.Controllers var API_URL = $"http://127.0.0.1:{httpConnectionFeature.LocalPort}/api/v8/"; try { - - var result = await biz.RenderReport(reportRequest,DateTime.UtcNow.AddMinutes(ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT), API_URL); - + var result = await biz.RenderReport(reportRequest, DateTime.UtcNow.AddMinutes(ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT), API_URL); if (string.IsNullOrWhiteSpace(result)) return BadRequest(new ApiErrorResponse(biz.Errors)); else return Ok(ApiOkResponse.Response(result)); } + catch (ReportRenderTimeOutException) + { + log.LogInformation($"Report render timeout report id: {reportRequest.ReportId}, record count:{reportRequest.SelectedRowIds.LongLength}, user:{UserNameFromContext.Name(HttpContext.Items)} "); + return Ok(ApiOkResponse.Response(new { timeout = true, timeoutconfig = ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT })); + } catch (System.Exception ex) { //The Javascript evaluation stack trace can be in the message making it long and internalized, diff --git a/server/AyaNova/biz/ContractBiz.cs b/server/AyaNova/biz/ContractBiz.cs index f2fa209a..48e033a9 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -557,7 +557,7 @@ MULTIPLE discount / markup ITEMS // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/CustomerBiz.cs b/server/AyaNova/biz/CustomerBiz.cs index a8758b61..5990b50d 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -400,7 +400,7 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/CustomerNoteBiz.cs b/server/AyaNova/biz/CustomerNoteBiz.cs index 504eb37d..756cdd0f 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -213,7 +213,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/CustomerServiceRequestBiz.cs b/server/AyaNova/biz/CustomerServiceRequestBiz.cs index 2def248e..b8d2290f 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -344,7 +344,7 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/HeadOfficeBiz.cs b/server/AyaNova/biz/HeadOfficeBiz.cs index a654ab1c..dc967c38 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -321,7 +321,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/IExportAbleObject.cs b/server/AyaNova/biz/IExportAbleObject.cs index 86230308..e217504a 100644 --- a/server/AyaNova/biz/IExportAbleObject.cs +++ b/server/AyaNova/biz/IExportAbleObject.cs @@ -1,6 +1,8 @@ using System.Threading.Tasks; using Newtonsoft.Json.Linq; using AyaNova.Models; +using System; + namespace AyaNova.Biz { /// @@ -11,7 +13,7 @@ namespace AyaNova.Biz //Get items indicated in id list in exportable format //called by ExportBiz rendering code - Task GetExportData(DataListSelectedRequest dataListSelectedRequest); + Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry); const int EXPORT_DATA_BATCH_SIZE = 100; } diff --git a/server/AyaNova/biz/LoanUnitBiz.cs b/server/AyaNova/biz/LoanUnitBiz.cs index 4e646243..f0537d2a 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -308,7 +308,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/MemoBiz.cs b/server/AyaNova/biz/MemoBiz.cs index 1e9c3d14..1bb06907 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -316,7 +316,7 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/PMBiz.cs b/server/AyaNova/biz/PMBiz.cs index cfd0f5f4..d291aa8f 100644 --- a/server/AyaNova/biz/PMBiz.cs +++ b/server/AyaNova/biz/PMBiz.cs @@ -812,7 +812,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 @@ -920,7 +920,7 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/PartAssemblyBiz.cs b/server/AyaNova/biz/PartAssemblyBiz.cs index e30f9588..6c406344 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -362,7 +362,7 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/PartBiz.cs b/server/AyaNova/biz/PartBiz.cs index a570d696..3f63c2eb 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -543,7 +543,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/PartInventoryBiz.cs b/server/AyaNova/biz/PartInventoryBiz.cs index aa6f10d1..b0a59a97 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -309,7 +309,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/PartInventoryDataListBiz.cs b/server/AyaNova/biz/PartInventoryDataListBiz.cs index ebc59d0f..3c787a4d 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -73,7 +73,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/PartInventoryRequestDataListBiz.cs b/server/AyaNova/biz/PartInventoryRequestDataListBiz.cs index 714ad1c5..40da2764 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -73,7 +73,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/PartWarehouseBiz.cs b/server/AyaNova/biz/PartWarehouseBiz.cs index d08fa641..0700a20c 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -314,7 +314,7 @@ namespace AyaNova.Biz // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/ProjectBiz.cs b/server/AyaNova/biz/ProjectBiz.cs index c9c4626d..0be1d22f 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -311,7 +311,7 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/PurchaseOrderBiz.cs b/server/AyaNova/biz/PurchaseOrderBiz.cs index 35c14ec8..a9d4f454 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -807,7 +807,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/QuoteBiz.cs b/server/AyaNova/biz/QuoteBiz.cs index 367cd191..83aa315d 100644 --- a/server/AyaNova/biz/QuoteBiz.cs +++ b/server/AyaNova/biz/QuoteBiz.cs @@ -787,7 +787,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // - public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 @@ -901,7 +901,7 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/ReminderBiz.cs b/server/AyaNova/biz/ReminderBiz.cs index df896550..c673e3bd 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -311,7 +311,7 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/ReportBiz.cs b/server/AyaNova/biz/ReportBiz.cs index 51b5f95c..786a7cc0 100644 --- a/server/AyaNova/biz/ReportBiz.cs +++ b/server/AyaNova/biz/ReportBiz.cs @@ -367,6 +367,8 @@ 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(); log.LogDebug($"Instantiating biz object handler for {selectedRequest.AType}"); var biz = BizObjectFactory.GetBizObject(selectedRequest.AType, ct, UserId, CurrentUserRoles, UserTranslationId); @@ -454,7 +456,7 @@ namespace AyaNova.Biz // #if (DEBUG) // log.LogInformation($"DBG: ReportBiz::RenderReport got report data"); // #endif - if (DateTime.UtcNow > renderTimeOutExpiry) + if (DateTime.UtcNow > renderTimeOutExpiry) throw new ReportRenderTimeOutException(); //initialization log.LogDebug("Initializing report rendering system"); @@ -514,6 +516,9 @@ namespace AyaNova.Biz } 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 now:"); // #if (DEBUG) @@ -523,7 +528,7 @@ namespace AyaNova.Biz using (var page = await browser.NewPageAsync()) { //track this process so it can be cancelled if it times out - ReportRenderManager.AddProcess(browser.Process.Id, log); + ReportRenderManager.AddProcess(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 { @@ -553,7 +558,8 @@ namespace AyaNova.Biz }; 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/ @@ -577,7 +583,8 @@ namespace AyaNova.Biz //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 @@ -632,7 +639,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 (DEBUG) // //view page contents @@ -647,15 +655,19 @@ namespace AyaNova.Biz // #endif //PRE_RENDER (WITH TIMEOUT???) await page.WaitForExpressionAsync($"ayPreRender({ReportDataObject})"); - + if (DateTime.UtcNow > renderTimeOutExpiry) + throw new ReportRenderTimeOutException(); //compile the template log.LogDebug($"Calling Handlebars.compile..."); // #if (DEBUG) // log.LogInformation($"DBG: ReportBiz::RenderReport - compiling handlebars template"); // #endif 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"); // #if (DEBUG) @@ -753,7 +765,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(); //render to pdf and return log.LogDebug($"Calling render page contents to PDF"); // #if (DEBUG) @@ -764,6 +777,10 @@ namespace AyaNova.Biz log.LogDebug($"Completed, returning results"); return outputFileName; } + catch (ReportRenderTimeOutException) + { + throw; + } catch { //This is the error when a helper is used on the template but doesn't exist: diff --git a/server/AyaNova/biz/ReviewBiz.cs b/server/AyaNova/biz/ReviewBiz.cs index 423822f0..55792a3c 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -378,7 +378,7 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/ServiceBankBiz.cs b/server/AyaNova/biz/ServiceBankBiz.cs index 90a8160f..147f7b55 100644 --- a/server/AyaNova/biz/ServiceBankBiz.cs +++ b/server/AyaNova/biz/ServiceBankBiz.cs @@ -264,7 +264,7 @@ // //////////////////////////////////////////////////////////////////////////////////////////////// // //REPORTING // // -// public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest) +// public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) // { // JArray ReportData = new JArray(); // while (idList.Any()) @@ -291,7 +291,7 @@ // // IMPORT EXPORT // // -// public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) +// public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) // { // //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 diff --git a/server/AyaNova/biz/ServiceRateBiz.cs b/server/AyaNova/biz/ServiceRateBiz.cs index 5ec98baa..f112f0ea 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -331,7 +331,7 @@ namespace AyaNova.Biz // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/TaskGroupBiz.cs b/server/AyaNova/biz/TaskGroupBiz.cs index 9f8fa3c1..d72ba643 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -316,7 +316,7 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/TaxCodeBiz.cs b/server/AyaNova/biz/TaxCodeBiz.cs index 994a5af4..84b99881 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -360,7 +360,7 @@ namespace AyaNova.Biz // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/TravelRateBiz.cs b/server/AyaNova/biz/TravelRateBiz.cs index bfe37cb0..3f770041 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -327,7 +327,7 @@ namespace AyaNova.Biz // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/UnitBiz.cs b/server/AyaNova/biz/UnitBiz.cs index 307e80d9..c64cc431 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -379,7 +379,7 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/UnitMeterReadingBiz.cs b/server/AyaNova/biz/UnitMeterReadingBiz.cs index cf17b145..5deb40f2 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -178,7 +178,7 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/UnitModelBiz.cs b/server/AyaNova/biz/UnitModelBiz.cs index e124b334..5bf02370 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -311,7 +311,7 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/UserBiz.cs b/server/AyaNova/biz/UserBiz.cs index f832dcf2..1275c404 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -1079,7 +1079,7 @@ namespace AyaNova.Biz // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/VendorBiz.cs b/server/AyaNova/biz/VendorBiz.cs index f7859992..bd56a9cb 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { var idList = dataListSelectedRequest.SelectedRowIds; JArray ReportData = new JArray(); @@ -344,7 +344,7 @@ namespace AyaNova.Biz // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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 diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index 9bd1167c..f81a4a86 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) + public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { // #if (DEBUG) // var watch = System.Diagnostics.Stopwatch.StartNew(); @@ -952,6 +952,8 @@ namespace AyaNova.Biz while (idList.Any()) { + if (DateTime.UtcNow > renderTimeOutExpiry) + throw new ReportRenderTimeOutException(); var batch = idList.Take(IReportAbleObject.REPORT_DATA_BATCH_SIZE); idList = idList.Skip(IReportAbleObject.REPORT_DATA_BATCH_SIZE).ToArray(); List batchResults = new List(); @@ -960,6 +962,8 @@ namespace AyaNova.Biz foreach (WorkOrder w in batchResults) { + if (DateTime.UtcNow > renderTimeOutExpiry) + throw new ReportRenderTimeOutException(); var jo = JObject.FromObject(w); //WorkOrder header custom fields @@ -1108,11 +1112,11 @@ namespace AyaNova.Biz // IMPORT EXPORT // - public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) + public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest, DateTime renderTimeOutExpiry) { //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); + return await GetReportData(dataListSelectedRequest, renderTimeOutExpiry); } //////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/server/AyaNova/util/ReportProcessManager.cs b/server/AyaNova/util/ReportProcessManager.cs index 5ab32732..1e2ad7e0 100644 --- a/server/AyaNova/util/ReportProcessManager.cs +++ b/server/AyaNova/util/ReportProcessManager.cs @@ -34,7 +34,7 @@ namespace AyaNova.Util internal static void KillExpiredRenders(ILogger log) { - log.LogTrace("Clear expired render check"); + log.LogDebug("Clear potential expired render jobs check"); //check for expired and remove var Instances = _baginstances.ToArray(); var dtNow = DateTime.UtcNow; @@ -52,7 +52,7 @@ namespace AyaNova.Util internal static bool ForceCloseProcess(ReportRenderInstanceInfo instance, ILogger log) { - log.LogTrace($"ForceCloseProcess on report render instance id {instance.ReporterProcessId} exired {instance.Expires.ToString()} utc"); + log.LogDebug($"ForceCloseProcess on report render instance id {instance.ReporterProcessId} exired {instance.Expires.ToString()} utc"); try { var p = Process.GetProcessById(instance.ReporterProcessId);