using System; using System.Collections.Generic; using System.IO; using Neo.Afx.ComponentModel; namespace Neo.Afx.Services { /// /// A scheduler that queries the for services. /// public class DatabaseServiceScheduler { List _serviceTasks; ServiceTaskScheduler _serviceTaskScheduler; long _systemUserID; #region Start /// /// Starts the scheduler. /// public void Start() { _serviceTasks = new List(); try { // Add services from the database // Create local instance because the underlying context is NOT thread-safe using(var serviceDatabase = new ServiceDatabase()) { _systemUserID = serviceDatabase.GetSystemUserID(); var systemUserEmail = serviceDatabase.GetSystemUserEmail(); foreach(var service in serviceDatabase.GetServices()) { try { var serviceTask = new ServiceTask( new ServiceSchedule((PollFrequencyEnum)service.PollFrequencyID, TimeSpan.Parse(service.PollTime)), service.ServiceID, service.ServiceName, (IExecutable)Worker.Create(service.ServiceTypeName, _systemUserID, systemUserEmail, service.Settings)); _serviceTasks.Add(serviceTask); } catch (Exception ex) { UpdateAuditLog("Start", ex, service.ServiceID); } } } _serviceTaskScheduler = new ServiceTaskScheduler(_serviceTasks); _serviceTaskScheduler.TaskBusy += OnServiceTaskBusy; _serviceTaskScheduler.TaskCompleted += OnServiceTaskCompleted; _serviceTaskScheduler.UnhandledError += OnUnhandledError; _serviceTaskScheduler.Start(); } catch(Exception ex) { UpdateAuditLog("Start", ex); } } #endregion #region Stop /// /// Stops the scheduler. /// public void Stop() { if(_serviceTaskScheduler != null) { _serviceTaskScheduler.TaskBusy -= OnServiceTaskBusy; _serviceTaskScheduler.TaskCompleted -= OnServiceTaskCompleted; _serviceTaskScheduler.UnhandledError -= OnUnhandledError; _serviceTaskScheduler = null; } if(_serviceTasks == null) { return; } _serviceTasks.Clear(); _serviceTasks = null; } #endregion #region OnServiceTaskBusy/Completed void OnServiceTaskBusy(object sender, ServiceTaskEventArgs e) { UpdateTraceLog(e.ServiceTask.ServiceID, e.SignalTime, "Service is busy"); } void OnServiceTaskCompleted(object sender, ServiceTaskEventArgs e) { if(e.ServiceTask.Exceptions != null) { foreach(var exception in e.ServiceTask.Exceptions) { UpdateAuditLog("run", exception, e.ServiceTask.ServiceID, e.ServiceTask.Schedule.LastRunTime); } } UpdateTraceLog(e.ServiceTask.ServiceID, e.ServiceTask.Schedule.LastRunTime, e.ServiceTask.TraceInfo); } #endregion #region OnUnhandledError void OnUnhandledError(object sender, ErrorEventArgs e) { UpdateAuditLog("Unhandled", e.GetException()); } #endregion #region Update Audit/Trace Log void UpdateAuditLog(string source, Exception ex, int? serviceID = null) { UpdateAuditLog(source, ex, serviceID, DateTime.Now); } void UpdateAuditLog(string source, Exception ex, int? serviceID, DateTime runDate) { UpdateRunStatus(serviceID, runDate, _systemUserID, string.Format("Service {0} error: {1}", source, ex.ToStringComplete()), string.Format("Service {0} error: {1}", source, ex.Message)); } void UpdateTraceLog(int serviceID, DateTime runDate, string traceInfo) { UpdateRunStatus(serviceID, runDate, _systemUserID, traceInfo, null); } static void UpdateRunStatus(int? serviceID, DateTime runDate, long updatedByID, string traceInfo, string auditInfo) { // Create local instance because the underlying context is NOT thread-safe using(var db = new ServiceDatabase()) { db.UpdateRunStatus(serviceID, runDate, updatedByID, traceInfo, auditInfo); } } #endregion } }