using System; using System.Linq; using System.Web; using System.Web.Caching; using System.Web.Mvc; using Hangfire; using LeafWeb.Core.Entities; using LeafWeb.Core.Utility; using LeafWeb.WebCms.Models; using LeafWeb.WebCms.Services; using LeafWeb.WebCms.Services.PiscalQueue; using LeafWeb.WebCms.Utility; using Umbraco.Web.Mvc; namespace LeafWeb.WebCms.Controllers { [MemberAuthorize(AllowGroup = "Administrator")] public class QueueController : BaseController { private const int TimeSamples = 40; public ActionResult Index(LeafDataQuery query) { var resultItems = DataService.GetLeafInputsOrdered(); resultItems = QueryFilter.Search(resultItems, query); var timeInProgressEstimater = TimeInProgressEstimater(); var serviceDescription = ServiceDescription(); var queueViewModel = new QueueViewModel { Items = resultItems, ServerDescription = serviceDescription, Q = query, TimeInProgressEstimater = timeInProgressEstimater }; return View(queueViewModel); } [HttpPost] public ActionResult Search(LeafDataQuery q) { if (!ModelState.IsValid) { return CurrentUmbracoPage(); } return RedirectToCurrentUmbracoPage(q.GetNameValueCollection()); } private TimeInProgressEstimater TimeInProgressEstimater() { // TODO: move this to a background process var estimater = HttpRuntime.Cache["TimeInProgressEstimater"]; if (estimater == null) { // completed leaf input for computing runtime statistics var completedLeafInput = DataService.GetLeafInputRecentlyCompleted(TimeSamples); estimater = new TimeInProgressEstimater(completedLeafInput); HttpRuntime.Cache.Insert("TimeInProgressEstimater", estimater, null, DateTime.Now.AddHours(12), Cache.NoSlidingExpiration); } return (TimeInProgressEstimater)estimater; } public ActionResult LeafInputStatistics() { var data = from li in DataService.GetLeafInputRecentlyCompleted(TimeSamples) select $"{li.InputFiles.Count}, {li.TimeInProgress.TotalSeconds}"; return Content(string.Join("
", data)); } private static string ServiceDescription() { string serviceDescription; try { serviceDescription = new PiscalService().ServiceDescription; } catch (Exception) { serviceDescription = "Exception while initializing"; } return serviceDescription; } public ActionResult Details(int id) { var leafInput = DataService.GetLeafInput(id); if (leafInput == null) { SetStatusMessage($"LeafInput '${id}' not found, may have been deleted?"); RedirectToUmbracoPage(LeafWebPageIds.ManageQueue); } var viewModel = new LeafInputDetails(leafInput); return View(viewModel); } public ActionResult DownloadInput(int id) { return GetInputZip(id); } public ActionResult DownloadOutputToUser(int id) { return GetOutputZip(id, LeafOutputFileType.ToUser); } public ActionResult DownloadOutputNotToUser(int id) { return GetOutputZip(id, LeafOutputFileType.NotToUser); } public ActionResult DownloadOutputCleanedInput(int id) { return GetOutputZip(id, LeafOutputFileType.CleanedInput); } private ActionResult GetOutputZip(int id, LeafOutputFileType type) { var leafInput = DataService.GetLeafInput(id); if (leafInput == null) return View("DownloadNotFound"); var zip = leafInput.GetOutputFileZip(type); var filename = $"{leafInput.Identifier.FilterValidFilename()}_{type}.zip"; return new FileContentResult(zip, "application/zip") { FileDownloadName = filename }; } private ActionResult GetInputZip(int id) { var leafInput = DataService.GetLeafInput(id); if (leafInput == null) return View("DownloadNotFound"); var zip = leafInput.GetInputFileZip(); var filename = $"{leafInput.Identifier.FilterValidFilename()}_Input.zip"; return new FileContentResult(zip, "application/zip") { FileDownloadName = filename }; } [ActionLog] public ActionResult Delete(int id) { var leafInput = DataService.GetLeafInput(id); if (leafInput == null) { SetStatusMessage($"LeafInput '${id}' not found, perhaps it is already deleted?"); return RedirectToUmbracoPage(LeafWebPageIds.ManageQueue); } // don't allow currently running LeafInput to be deleted if (leafInput.IsInProgress) { SetStatusMessage($"LeafInput '{leafInput.Identifier}' is currently running!", StatusType.Error); return RedirectToCurrentUmbracoUrl(); } DataService.DeleteLeafInput(leafInput); SetStatusMessage($"LeafInput '{leafInput.Identifier}' deleted", StatusType.Success); return RedirectToUmbracoPage(LeafWebPageIds.ManageQueue); } [ActionLog] public ActionResult Cancel(int id) { var leafInput = DataService.GetLeafInput(id); if (leafInput == null) { SetStatusMessage($"LeafInput '${id}' not found, may have been deleted?"); return RedirectToUmbracoPage(LeafWebPageIds.ManageQueue); } var cancelPendingSuccess = new PiscalQueueManager().CancelPending(id); if (cancelPendingSuccess) { SetStatusMessage($"Cancelling LeafInput '{leafInput.Identifier}'", StatusType.Success); } else { // don't allow to be cancelled if it isn't currently running SetStatusMessage($"Couldn't cancel '{leafInput.Identifier}', is it currently running?", StatusType.Error); } return RedirectToCurrentUmbracoUrl(); } [ActionLog] public ActionResult SendUserDownloadLink(int id) { var leafInput = DataService.GetLeafInput(id); if (leafInput == null) { SetStatusMessage($"LeafInput '${id}' not found, may have been deleted?"); } else if (!leafInput.IsComplete) { SetStatusMessage($"LeafInput '{leafInput.Identifier}' is not complete!", StatusType.Error); } else { var leafInputId = leafInput.Id; BackgroundJob.Enqueue(e => e.SendLeafWebComplete(leafInputId)); SetStatusMessage($"LeafInput '{leafInput.Identifier}' download link sent", StatusType.Success); } return RedirectToCurrentUmbracoUrl(); } [ActionLog] public ActionResult Priority(int id, Priority priority) { var leafInput = DataService.GetLeafInput(id); if (leafInput == null) { SetStatusMessage($"LeafInput '${id}' not found, may have been deleted?"); } else if (!leafInput.IsPending) { SetStatusMessage($"LeafInput '{leafInput.Identifier}' is no longer pending"); } else { leafInput.PendingPriority = priority; DataService.UpdateLeafInput(leafInput); SetStatusMessage($"LeafInput '{leafInput.Identifier}' priority set to '{leafInput.PendingPriority}'", StatusType.Success); } return RedirectToCurrentUmbracoUrl(); } [ActionLog] public ActionResult SendUserChartLink(int id) { throw new System.NotImplementedException(); } } }