using System; using System.Diagnostics; using System.Threading.Tasks; using Microsoft.Extensions.Logging; namespace AyaNova.Util { /// /// Used by reporting system to ensure headless browsers don't hang around in an untimely manner /// needed due to bugs in puppeteersharp where it won't close the browser on timeout properly /// also zombie process issues in linux etc, this just ensures it's safe /// This is triggered when a report is rendered /// internal static class ReportProcessorManager { internal static int ReporterProcessId { get; set; } = -1; internal static DateTime Started { get; set; } internal async static Task EnsureReporterAvailableAsync(ILogger log) { Process reportProcess = ReporterProcess(); if (reportProcess == null) { return; } //await it's completion in the specified timeout int HardTimeout = ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT; //don't wait forever, hard cap of 3 minutes regardless of setting if (HardTimeout > 180000) HardTimeout = 180000; bool keepOnWaiting = true; while (keepOnWaiting) { //don't check continually await Task.Delay(500); //check process is still running if (reportProcess?.HasExited == false) { //time to kill it? if ((DateTime.UtcNow - Started).TotalMilliseconds > HardTimeout) { log.LogInformation($"Report processor did not complete in {HardTimeout}ms and will be force stopped"); reportProcess.Kill(); keepOnWaiting = false; } } else { log.LogDebug($"EnsureReporterAvailableAsync Reporter processor completed normally"); keepOnWaiting = false; } }; ReporterProcessId = -1; Started = DateTime.MinValue; return; } internal static void RecordNewReportGeneratorProcess(int processId) { ReporterProcessId = processId; Started = DateTime.UtcNow; } private static Process ReporterProcess() { if (ReporterProcessId == -1) return null; try { return Process.GetProcessById(ReporterProcessId); } catch (ArgumentException) { return null;//no process available / not running } } /* //Is the report generator (browser) already running? if(ReportingProcessCache.ReporterProcess()!=null){ //there is an existing process in action, let's wait for timeout seconds and kill it if it's still running before proceeding //first check to see if it's still actually running or not: var process = System.Diagnostics.Process.GetProcessById(ReportingProcessCache.ReporterProcessId); // if (ChromiumProcessID > 0 && process?.HasExited == false) // { // log.LogError($"Error during render, Chromium process (pid {ChromiumProcessID}) still active, forcing it to stop now"); // process.Kill(); // } bool keepOnWaiting=true; while(keepOnWaiting){ var v= DateTime.UtcNow-ReportingProcessCache.Started; if(v.TotalSeconds> ServerBootConfig.REPORT_RENDERING_OPERATION_TIMEOUT){ } } } */ }//eoc }//eons