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
}
}