using System; using System.Configuration; using System.Diagnostics; using System.IO; using System.Timers; namespace ChadSoft.Edificator.Service { public class RunnerExceptionEventArgs : EventArgs { public Exception Exception { get; set; } public RunnerExceptionEventArgs(Exception ex) { Exception = ex; } } public class Runner : IDisposable { private const string SpecificDailyTimeConfigKey = "EdificationService.SpecificDailyTime"; private const string IntervalConfigKey = "EdificationService.Interval"; private const int ThirtySeconds = 300; private readonly WisdomService _wisdomService; private readonly Timer _timer; private StreamWriter _outputWriter; private TextWriterTraceListener _debugWriter; public event EventHandler Exception; private static TimeSpan? _specificDailyTime; protected static TimeSpan? SpecificDailyTime { get { if (_specificDailyTime == null) _specificDailyTime = ParseTimeSpanFromConfiguration(SpecificDailyTimeConfigKey); return _specificDailyTime; } } private static TimeSpan? _interval; protected static TimeSpan? Interval { get { if (_interval == null) _interval = ParseTimeSpanFromConfiguration(IntervalConfigKey); return _interval; } } public Runner() : this(new WisdomService(), new Timer()) { } public Runner(WisdomService wisdomService, Timer timer) { _timer = timer; _wisdomService = wisdomService; ConfigureLogging(); } public void Start() { // If we are set to send at a specific time every day, // just check every 30 seconds if it's that time yet if (SpecificDailyTime.HasValue) _timer.Interval = ThirtySeconds; // Otherwise trigger at the interval else if (Interval.HasValue) _timer.Interval = Interval.Value.Milliseconds; else throw new ApplicationException(string.Format( "Neither {0} nor {1} configuration settings were set - please set one.", SpecificDailyTimeConfigKey, IntervalConfigKey)); _timer.Elapsed += ((x, y) => Edificate()); } private void Edificate() { try { bool shouldSend; if(SpecificDailyTime.HasValue) shouldSend = (DateTime.Now.TimeOfDay == SpecificDailyTime.Value); else shouldSend = true; if (shouldSend) _wisdomService.Edificate(); } catch (Exception e) { InvokeException(new RunnerExceptionEventArgs(e)); } } public void Stop() { _timer.Stop(); } private void ConfigureLogging() { string outputLogFile = ConfigurationManager.AppSettings["OutputLogFile"]; if (!string.IsNullOrEmpty(outputLogFile)) { string fullOutputLogFile = Path.GetFullPath(outputLogFile); _outputWriter = new StreamWriter(fullOutputLogFile, true); Console.SetOut(_outputWriter); } string debugLogFile = ConfigurationManager.AppSettings["DebugLogFile"]; if (!string.IsNullOrEmpty(debugLogFile)) { string fullDebugLogFile = Path.GetFullPath(debugLogFile); _debugWriter = new TextWriterTraceListener(fullDebugLogFile); Debug.Listeners.Add(_debugWriter); Debug.AutoFlush = true; } } public void Dispose() { if (_outputWriter != null) _outputWriter.Dispose(); if (_debugWriter != null) _debugWriter.Dispose(); } private static TimeSpan? ParseTimeSpanFromConfiguration(string configKey) { string timeValue = ConfigurationManager.AppSettings[configKey]; TimeSpan parsedTime; if (TimeSpan.TryParse(timeValue, out parsedTime)) return parsedTime; else { return null; } } private void InvokeException(RunnerExceptionEventArgs args) { EventHandler exception = Exception; if (exception != null) exception(this, args); } } }