using System; using System.Linq; using System.Threading; using LeafWeb.Core.DAL; using LeafWeb.Core.Entities; using LeafWeb.Core.Remote; using NLog; namespace LeafWeb.Web.Services { public class PiscalQueueManager : IDisposable { private readonly DataService _dataService; private readonly PiscalService _piscalService; public PiscalQueueManager(DataService dataService, PiscalService piscalService) { _dataService = dataService; _piscalService = piscalService; } public PiscalQueueManager() : this(new DataService(), new PiscalService()) {} private static readonly object ProcessQueueLock = new object(); public void ProcessQueue() { var logger = LogManager.GetCurrentClassLogger(); if (Monitor.TryEnter(ProcessQueueLock)) { logger.Trace("ProcessQueue entered"); ProcessRunning(logger); ProcessQueue(logger); logger.Trace("ProcessQueue completed"); Monitor.Exit(ProcessQueueLock); } else { logger.Trace("ProcessQueue locked, queue already processing"); } } private void ProcessQueue(ILogger logger) { var runningLeafInputFiles = _dataService.GetLeafInputFiles(LeafInputStatusType.Running).ToList(); if (runningLeafInputFiles.Any()) return; var queuedFile = _dataService .GetLeafInputFiles(LeafInputStatusType.Queued) .OrderBy(l => l.Id) .FirstOrDefault(); if (queuedFile == null) return; logger.Info("LeafInputFile: {0}, Start", queuedFile.Id); _piscalService.Run(queuedFile); _dataService.SetLeafInputFileStatus(queuedFile, LeafInputStatusType.Running); } private void ProcessRunning(ILogger logger) { var runningLeafInputFiles = _dataService.GetLeafInputFiles(LeafInputStatusType.Running).ToList(); foreach (var file in runningLeafInputFiles) { var status = _piscalService.GetStatus(file); switch (status) { case PiscalStatus.Running: logger.Trace("LeafInputFile: {0}, {1}", file.Id, status); // continue running break; case PiscalStatus.Success: logger.Info("LeafInputFile: {0}, {1}", file.Id, status); // collect the leaf output var leafOutputFiles = _piscalService.RetrieveOutputFiles(file).ToList(); foreach (var outputFile in leafOutputFiles) _dataService.AddLeafOutputFile(outputFile); logger.Info("LeafInputFile: {0}, output files: {1}", file.Id, string.Join(", ", leafOutputFiles.Select(o => o.Filename))); // update db _dataService.SetLeafInputFileStatus(file, LeafInputStatusType.Complete); // remove working data from the server logger.Info("LeafInputFile: {0}, cleanup", file.Id); _piscalService.Cleanup(file); break; case PiscalStatus.Error: logger.Info("LeafInputFile: {0}, error", file.Id); _dataService.SetLeafInputFileStatus(file, LeafInputStatusType.Error); break; } } } public void Dispose() { _dataService.Dispose(); } } }