From 9ecb890afdfdc86b3dba3667f5b4fc16b1bf65f8 Mon Sep 17 00:00:00 2001 From: Dariusz Danielewski Date: Wed, 30 Aug 2017 16:55:12 -0500 Subject: [PATCH] Code cleanup and parallelized execution and abort --- CronNET/CronDaemon.cs | 29 +++---- CronNET/CronJob.cs | 35 ++++---- CronNET/CronNET.csproj | 3 + CronNET/CronSchedule.cs | 124 +++++++++++++--------------- CronNET/Interfaces/ICronDaemon.cs | 11 +++ CronNET/Interfaces/ICronJob.cs | 10 +++ CronNET/Interfaces/ICronSchedule.cs | 10 +++ CronNETTests/CronScheduleTests.cs | 82 +++++++++--------- 8 files changed, 158 insertions(+), 146 deletions(-) create mode 100644 CronNET/Interfaces/ICronDaemon.cs create mode 100644 CronNET/Interfaces/ICronJob.cs create mode 100644 CronNET/Interfaces/ICronSchedule.cs diff --git a/CronNET/CronDaemon.cs b/CronNET/CronDaemon.cs index ae612fd..5b185c5 100755 --- a/CronNET/CronDaemon.cs +++ b/CronNET/CronDaemon.cs @@ -2,45 +2,37 @@ using System; using System.Collections.Generic; using System.Timers; using System.Threading; +using System.Threading.Tasks; +using CronNET.Interfaces; namespace CronNET { - public interface ICronDaemon - { - void AddJob(string schedule, ThreadStart action); - void Start(); - void Stop(); - } - public class CronDaemon : ICronDaemon { - private readonly System.Timers.Timer timer = new System.Timers.Timer(30000); - private readonly List cron_jobs = new List(); + private readonly System.Timers.Timer _timer = new System.Timers.Timer(10000){AutoReset = true}; + private readonly List _cronJobs = new List(); private DateTime _last= DateTime.Now; public CronDaemon() { - timer.AutoReset = true; - timer.Elapsed += timer_elapsed; + _timer.Elapsed += timer_elapsed; } public void AddJob(string schedule, ThreadStart action) { var cj = new CronJob(schedule, action); - cron_jobs.Add(cj); + _cronJobs.Add(cj); } public void Start() { - timer.Start(); + _timer.Start(); } public void Stop() { - timer.Stop(); - - foreach (CronJob job in cron_jobs) - job.abort(); + _timer.Stop(); + Parallel.ForEach(_cronJobs, job => job.Abort()); } private void timer_elapsed(object sender, ElapsedEventArgs e) @@ -48,8 +40,7 @@ namespace CronNET if (DateTime.Now.Minute != _last.Minute) { _last = DateTime.Now; - foreach (ICronJob job in cron_jobs) - job.execute(DateTime.Now); + Parallel.ForEach(_cronJobs, job => job.Execute(DateTime.Now)); } } } diff --git a/CronNET/CronJob.cs b/CronNET/CronJob.cs index 97f2b05..00fd509 100755 --- a/CronNET/CronJob.cs +++ b/CronNET/CronJob.cs @@ -1,47 +1,42 @@ using System; using System.Threading; +using CronNET.Interfaces; namespace CronNET { - public interface ICronJob - { - void execute(DateTime date_time); - void abort(); - } - public class CronJob : ICronJob { - private readonly ICronSchedule _cron_schedule = new CronSchedule(); - private readonly ThreadStart _thread_start; + private readonly ICronSchedule _cronSchedule; + + private readonly object _lock = new object(); + private readonly ThreadStart _threadStart; private Thread _thread; - public CronJob(string schedule, ThreadStart thread_start) + public CronJob(string schedule, ThreadStart threadStart) { - _cron_schedule = new CronSchedule(schedule); - _thread_start = thread_start; - _thread = new Thread(thread_start); + _cronSchedule = new CronSchedule(schedule); + _threadStart = threadStart; + _thread = new Thread(threadStart); } - private object _lock = new object(); - public void execute(DateTime date_time) + public void Execute(DateTime dateTime) { lock (_lock) { - if (!_cron_schedule.isTime(date_time)) + if (!_cronSchedule.IsTime(dateTime)) return; if (_thread.ThreadState == ThreadState.Running) return; - _thread = new Thread(_thread_start); + _thread = new Thread(_threadStart); _thread.Start(); } } - public void abort() + public void Abort() { - _thread.Abort(); + _thread.Abort(); } - } -} +} \ No newline at end of file diff --git a/CronNET/CronNET.csproj b/CronNET/CronNET.csproj index 62d75b3..f1bc607 100755 --- a/CronNET/CronNET.csproj +++ b/CronNET/CronNET.csproj @@ -43,6 +43,9 @@ + + + diff --git a/CronNET/CronSchedule.cs b/CronNET/CronSchedule.cs index 5b6dfb6..99049d7 100755 --- a/CronNET/CronSchedule.cs +++ b/CronNET/CronSchedule.cs @@ -1,35 +1,30 @@ using System; using System.Collections.Generic; using System.Text.RegularExpressions; +using CronNET.Interfaces; namespace CronNET { - public interface ICronSchedule - { - bool isValid(string expression); - bool isTime(DateTime date_time); - } - public class CronSchedule : ICronSchedule { #region Readonly Class Members - readonly static Regex divided_regex = new Regex(@"(\*/\d+)"); - readonly static Regex range_regex = new Regex(@"(\d+\-\d+)\/?(\d+)?"); - readonly static Regex wild_regex = new Regex(@"(\*)"); - readonly static Regex list_regex = new Regex(@"(((\d+,)*\d+)+)"); - readonly static Regex validation_regex = new Regex(divided_regex + "|" + range_regex + "|" + wild_regex + "|" + list_regex); + static readonly Regex DividedRegex = new Regex(@"(\*/\d+)"); + static readonly Regex RangeRegex = new Regex(@"(\d+\-\d+)\/?(\d+)?"); + static readonly Regex WildRegex = new Regex(@"(\*)"); + static readonly Regex ListRegex = new Regex(@"(((\d+,)*\d+)+)"); + static readonly Regex ValidationRegex = new Regex(DividedRegex + "|" + RangeRegex + "|" + WildRegex + "|" + ListRegex); #endregion #region Private Instance Members private readonly string _expression; - public List minutes; - public List hours; - public List days_of_month; - public List months; - public List days_of_week; + private List _minutes; + private List _hours; + private List _daysOfMonth; + private List _months; + private List _daysOfWeek; #endregion @@ -41,101 +36,99 @@ namespace CronNET public CronSchedule(string expressions) { - this._expression = expressions; - generate(); + _expression = expressions; + Generate(); } + public List Minutes => _minutes; + + public List Hours => _hours; + + public List DaysOfMonth => _daysOfMonth; + + public List Months => _months; + + public List DaysOfWeek => _daysOfWeek; + #endregion #region Public Methods - private bool isValid() + private bool IsValid() { - return isValid(this._expression); + return IsValid(_expression); } - public bool isValid(string expression) + public bool IsValid(string expression) { - MatchCollection matches = validation_regex.Matches(expression); + MatchCollection matches = ValidationRegex.Matches(expression); return matches.Count > 0;//== 5; } - public bool isTime(DateTime date_time) + public bool IsTime(DateTime dateTime) { - return minutes.Contains(date_time.Minute) && - hours.Contains(date_time.Hour) && - days_of_month.Contains(date_time.Day) && - months.Contains(date_time.Month) && - days_of_week.Contains((int)date_time.DayOfWeek); + return _minutes.Contains(dateTime.Minute) && + _hours.Contains(dateTime.Hour) && + _daysOfMonth.Contains(dateTime.Day) && + _months.Contains(dateTime.Month) && + _daysOfWeek.Contains((int)dateTime.DayOfWeek); } - private void generate() + private void Generate() { - if (!isValid()) return; + if (!IsValid()) return; - MatchCollection matches = validation_regex.Matches(this._expression); + MatchCollection matches = ValidationRegex.Matches(_expression); generate_minutes(matches[0].ToString()); - if (matches.Count > 1) - generate_hours(matches[1].ToString()); - else - generate_hours("*"); - - if (matches.Count > 2) - generate_days_of_month(matches[2].ToString()); - else - generate_days_of_month("*"); - - if (matches.Count > 3) - generate_months(matches[3].ToString()); - else - generate_months("*"); - - if (matches.Count > 4) - generate_days_of_weeks(matches[4].ToString()); - else - generate_days_of_weeks("*"); + generate_hours(matches.Count > 1 ? matches[1].ToString() : "*"); + + generate_days_of_month(matches.Count > 2 ? matches[2].ToString() : "*"); + + generate_months(matches.Count > 3 ? matches[3].ToString() : "*"); + + generate_days_of_weeks(matches.Count > 4 ? matches[4].ToString() : "*"); } private void generate_minutes(string match) { - this.minutes = generate_values(match, 0, 60); + _minutes = generate_values(match, 0, 60); } private void generate_hours(string match) { - this.hours = generate_values(match, 0, 24); + _hours = generate_values(match, 0, 24); } private void generate_days_of_month(string match) { - this.days_of_month = generate_values(match, 1, 32); + _daysOfMonth = generate_values(match, 1, 32); } private void generate_months(string match) { - this.months = generate_values(match, 1, 13); + _months = generate_values(match, 1, 13); } private void generate_days_of_weeks(string match) { - this.days_of_week = generate_values(match, 0, 7); + _daysOfWeek = generate_values(match, 0, 7); } private List generate_values(string configuration, int start, int max) { - if (divided_regex.IsMatch(configuration)) return divided_array(configuration, start, max); - if (range_regex.IsMatch(configuration)) return range_array(configuration); - if (wild_regex.IsMatch(configuration)) return wild_array(configuration, start, max); - if (list_regex.IsMatch(configuration)) return list_array(configuration); + if (DividedRegex.IsMatch(configuration)) return divided_array(configuration, start, max); + if (RangeRegex.IsMatch(configuration)) return range_array(configuration); + if (WildRegex.IsMatch(configuration)) return wild_array(configuration, start, max); + if (ListRegex.IsMatch(configuration)) return list_array(configuration); return new List(); } private List divided_array(string configuration, int start, int max) { - if (!divided_regex.IsMatch(configuration)) + if (!DividedRegex.IsMatch(configuration)) return new List(); List ret = new List(); @@ -151,13 +144,13 @@ namespace CronNET private List range_array(string configuration) { - if (!range_regex.IsMatch(configuration)) + if (!RangeRegex.IsMatch(configuration)) return new List(); List ret = new List(); string[] split = configuration.Split("-".ToCharArray()); int start = int.Parse(split[0]); - int end = 0; + int end; if (split[1].Contains("/")) { split = split[1].Split("/".ToCharArray()); @@ -169,8 +162,7 @@ namespace CronNET ret.Add(i); return ret; } - else - end = int.Parse(split[1]); + end = int.Parse(split[1]); for (int i = start; i <= end; ++i) ret.Add(i); @@ -180,7 +172,7 @@ namespace CronNET private List wild_array(string configuration, int start, int max) { - if (!wild_regex.IsMatch(configuration)) + if (!WildRegex.IsMatch(configuration)) return new List(); List ret = new List(); @@ -193,7 +185,7 @@ namespace CronNET private List list_array(string configuration) { - if (!list_regex.IsMatch(configuration)) + if (!ListRegex.IsMatch(configuration)) return new List(); List ret = new List(); diff --git a/CronNET/Interfaces/ICronDaemon.cs b/CronNET/Interfaces/ICronDaemon.cs new file mode 100644 index 0000000..6d10dfc --- /dev/null +++ b/CronNET/Interfaces/ICronDaemon.cs @@ -0,0 +1,11 @@ +using System.Threading; + +namespace CronNET.Interfaces +{ + public interface ICronDaemon + { + void AddJob(string schedule, ThreadStart action); + void Start(); + void Stop(); + } +} \ No newline at end of file diff --git a/CronNET/Interfaces/ICronJob.cs b/CronNET/Interfaces/ICronJob.cs new file mode 100644 index 0000000..a6eb3a8 --- /dev/null +++ b/CronNET/Interfaces/ICronJob.cs @@ -0,0 +1,10 @@ +using System; + +namespace CronNET.Interfaces +{ + public interface ICronJob + { + void Execute(DateTime dateTime); + void Abort(); + } +} \ No newline at end of file diff --git a/CronNET/Interfaces/ICronSchedule.cs b/CronNET/Interfaces/ICronSchedule.cs new file mode 100644 index 0000000..cb31cc5 --- /dev/null +++ b/CronNET/Interfaces/ICronSchedule.cs @@ -0,0 +1,10 @@ +using System; + +namespace CronNET.Interfaces +{ + public interface ICronSchedule + { + bool IsValid(string expression); + bool IsTime(DateTime dateTime); + } +} \ No newline at end of file diff --git a/CronNETTests/CronScheduleTests.cs b/CronNETTests/CronScheduleTests.cs index 8cb4fd3..9f4e20c 100755 --- a/CronNETTests/CronScheduleTests.cs +++ b/CronNETTests/CronScheduleTests.cs @@ -15,22 +15,22 @@ namespace CronTests public void is_valid_test() { var cron_schedule = new CronSchedule(); - Assert.IsTrue(cron_schedule.isValid("*/2")); - Assert.IsTrue(cron_schedule.isValid("* * * * *")); - Assert.IsTrue(cron_schedule.isValid("0 * * * *")); - Assert.IsTrue(cron_schedule.isValid("0,1,2 * * * *")); - Assert.IsTrue(cron_schedule.isValid("*/2 * * * *")); - Assert.IsTrue(cron_schedule.isValid("1-4 * * * *")); - Assert.IsTrue(cron_schedule.isValid("1-55/3 * * * *")); - Assert.IsTrue(cron_schedule.isValid("1,10,20 * * * *")); - Assert.IsTrue(cron_schedule.isValid("* 1,10,20 * * *")); + Assert.IsTrue(cron_schedule.IsValid("*/2")); + Assert.IsTrue(cron_schedule.IsValid("* * * * *")); + Assert.IsTrue(cron_schedule.IsValid("0 * * * *")); + Assert.IsTrue(cron_schedule.IsValid("0,1,2 * * * *")); + Assert.IsTrue(cron_schedule.IsValid("*/2 * * * *")); + Assert.IsTrue(cron_schedule.IsValid("1-4 * * * *")); + Assert.IsTrue(cron_schedule.IsValid("1-55/3 * * * *")); + Assert.IsTrue(cron_schedule.IsValid("1,10,20 * * * *")); + Assert.IsTrue(cron_schedule.IsValid("* 1,10,20 * * *")); } [Test] public static void divided_array_test() { var cron_schedule = new CronSchedule("*/2"); - List results = cron_schedule.minutes.GetRange(0,5);//("*/2", 0, 10); + List results = cron_schedule.Minutes.GetRange(0,5);//("*/2", 0, 10); Assert.AreEqual(results.ToArray(), new int[] { 0, 2, 4, 6, 8 }); } @@ -38,10 +38,10 @@ namespace CronTests public static void range_array_test() { var cron_schedule = new CronSchedule("1-10"); - List results = cron_schedule.minutes.GetRange(0,10);//(); + List results = cron_schedule.Minutes.GetRange(0,10);//(); Assert.AreEqual(results.ToArray(), new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); var cs = new CronSchedule("1-10/3 20-45/4 * * *"); - results = cs.minutes; + results = cs.Minutes; Assert.AreEqual(results.ToArray(), new int[] { 3, 6, 9 }); } @@ -49,7 +49,7 @@ namespace CronTests public void wild_array_test() { var cron_schedule = new CronSchedule("*"); - List results = cron_schedule.minutes.GetRange(0,10);//("*", 0, 10); + List results = cron_schedule.Minutes.GetRange(0,10);//("*", 0, 10); Assert.AreEqual(results.ToArray(), new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); } @@ -57,7 +57,7 @@ namespace CronTests public void list_array_test() { var cron_schedule = new CronSchedule("1,2,3,4,5,6,7,8,9,10"); - List results = cron_schedule.minutes; + List results = cron_schedule.Minutes; Assert.AreEqual(results.ToArray(), new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); } @@ -65,7 +65,7 @@ namespace CronTests public void generate_values_divided_test() { var cron_schedule = new CronSchedule("*/2"); - List results = cron_schedule.minutes.GetRange(0,5);//(, 0, 10); + List results = cron_schedule.Minutes.GetRange(0,5);//(, 0, 10); Assert.AreEqual(results.ToArray(), new int[] { 0, 2, 4, 6, 8 }); } @@ -73,7 +73,7 @@ namespace CronTests public void generate_values_range_test() { var cron_schedule = new CronSchedule("1-10"); - List results = cron_schedule.minutes.GetRange(0,10);//(, 0, 10); + List results = cron_schedule.Minutes.GetRange(0,10);//(, 0, 10); Assert.AreEqual(results.ToArray(), new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); } @@ -81,103 +81,103 @@ namespace CronTests public void generate_minutes_test() { var cron_schedule = new CronSchedule("1,2,3 * * * *"); - Assert.AreEqual(cron_schedule.minutes.ToArray(), new int[] { 1, 2, 3 }); + Assert.AreEqual(cron_schedule.Minutes.ToArray(), new int[] { 1, 2, 3 }); } [Test] public void generate_hours_test() { var cron_schedule = new CronSchedule("* 1,2,3 * * *"); - Assert.AreEqual(cron_schedule.hours.ToArray(), new int[] { 1, 2, 3 }); + Assert.AreEqual(cron_schedule.Hours.ToArray(), new int[] { 1, 2, 3 }); } [Test] public void generate_days_of_month_test() { var cron_schedule = new CronSchedule("* * 1,2,3 * *"); - Assert.AreEqual(cron_schedule.days_of_month.ToArray(), new int[] { 1, 2, 3 }); + Assert.AreEqual(cron_schedule.DaysOfMonth.ToArray(), new int[] { 1, 2, 3 }); } [Test] public void generate_months_test() { var cron_schedule = new CronSchedule("* * * 1,2,3 *"); - Assert.AreEqual(cron_schedule.months.ToArray(), new int[] { 1, 2, 3 }); + Assert.AreEqual(cron_schedule.Months.ToArray(), new int[] { 1, 2, 3 }); } [Test] public void generate_days_of_weeks() { var cron_schedule = new CronSchedule("* * * * 1,2,3 "); - Assert.AreEqual(cron_schedule.days_of_week.ToArray(), new int[] { 1, 2, 3 }); + Assert.AreEqual(cron_schedule.DaysOfWeek.ToArray(), new int[] { 1, 2, 3 }); } [Test] public void is_time_minute_test() { var cron_schedule = new CronSchedule("0 * * * *"); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("8:00 am"))); - Assert.IsFalse(cron_schedule.isTime(DateTime.Parse("8:01 am"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("8:00 am"))); + Assert.IsFalse(cron_schedule.IsTime(DateTime.Parse("8:01 am"))); cron_schedule = new CronSchedule("0-10 * * * *"); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("8:00 am"))); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("8:03 am"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("8:00 am"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("8:03 am"))); cron_schedule = new CronSchedule("*/2 * * * *"); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("8:00 am"))); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("8:02 am"))); - Assert.IsFalse(cron_schedule.isTime(DateTime.Parse("8:03 am"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("8:00 am"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("8:02 am"))); + Assert.IsFalse(cron_schedule.IsTime(DateTime.Parse("8:03 am"))); } [Test] public void is_time_hour_test() { var cron_schedule = new CronSchedule("* 0 * * *"); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("12:00 am"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("12:00 am"))); cron_schedule = new CronSchedule("* 0,12 * * *"); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("12:00 am"))); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("12:00 pm"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("12:00 am"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("12:00 pm"))); } [Test] public void is_time_day_of_month_test() { var cron_schedule = new CronSchedule("* * 1 * *"); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("2010/08/01"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("2010/08/01"))); } [Test] public void is_time_month_test() { var cron_schedule = new CronSchedule("* * * 1 *"); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("1/1/2008"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("1/1/2008"))); cron_schedule = new CronSchedule("* * * 12 *"); - Assert.IsFalse(cron_schedule.isTime(DateTime.Parse("1/1/2008"))); + Assert.IsFalse(cron_schedule.IsTime(DateTime.Parse("1/1/2008"))); cron_schedule = new CronSchedule("* * * */3 *"); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("3/1/2008"))); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("6/1/2008"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("3/1/2008"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("6/1/2008"))); } [Test] public void is_time_day_of_week_test() { var cron_schedule = new CronSchedule("* * * * 0"); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("10/12/2008"))); - Assert.IsFalse(cron_schedule.isTime(DateTime.Parse("10/13/2008"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("10/12/2008"))); + Assert.IsFalse(cron_schedule.IsTime(DateTime.Parse("10/13/2008"))); cron_schedule = new CronSchedule("* * * * */2"); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("10/14/2008"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("10/14/2008"))); } [Test] public void is_time_test() { var cron_schedule = new CronSchedule("0 0 12 10 *"); - Assert.IsTrue(cron_schedule.isTime(DateTime.Parse("12:00:00 am 10/12/2008"))); - Assert.IsFalse(cron_schedule.isTime(DateTime.Parse("12:01:00 am 10/12/2008"))); + Assert.IsTrue(cron_schedule.IsTime(DateTime.Parse("12:00:00 am 10/12/2008"))); + Assert.IsFalse(cron_schedule.IsTime(DateTime.Parse("12:01:00 am 10/12/2008"))); } [Test]