diff --git a/SchedulingPractice.SubWorkerRunner/Program.cs b/SchedulingPractice.SubWorkerRunner/Program.cs index ea5924b..2e51048 100644 --- a/SchedulingPractice.SubWorkerRunner/Program.cs +++ b/SchedulingPractice.SubWorkerRunner/Program.cs @@ -50,6 +50,7 @@ static void Main(string[] args) }); } else if (mode == "acetaxxxx") services.AddHostedService(); + else if (mode == "jim") services.AddHostedService(); else { throw new ArgumentOutOfRangeException($"Mode: {mode} not is not valid."); } }) .Build(); diff --git a/SchedulingPractice.SubWorkerRunner/SchedulingPractice.SubWorkerRunner.csproj b/SchedulingPractice.SubWorkerRunner/SchedulingPractice.SubWorkerRunner.csproj index dfad027..3834677 100644 --- a/SchedulingPractice.SubWorkerRunner/SchedulingPractice.SubWorkerRunner.csproj +++ b/SchedulingPractice.SubWorkerRunner/SchedulingPractice.SubWorkerRunner.csproj @@ -14,6 +14,7 @@ + diff --git a/SchedulingPractice.sln b/SchedulingPractice.sln index 10fa63e..2a12853 100644 --- a/SchedulingPractice.sln +++ b/SchedulingPractice.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29215.179 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32819.101 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SchedulingPractice.Core", "SchedulingPractice.Core\SchedulingPractice.Core.csproj", "{4E411DD0-16E8-4BD9-BA79-D22D1F4FE9B1}" EndProject @@ -11,10 +11,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SubWorker.AndrewDemo", "Sub EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{927CF37F-7C8C-426E-B63C-1121CA9FE062}" ProjectSection(SolutionItems) = preProject + andrew0928demoworker.cmd = andrew0928demoworker.cmd + andydemoworker.cmd = andydemoworker.cmd database.sql = database.sql demo-all.cmd = demo-all.cmd demo.cmd = demo.cmd + init.cmd = init.cmd README.md = README.md + jimdemoall.cmd = jimdemoall.cmd + jimdemoha.cmd = jimdemoha.cmd + jimdemoworker.cmd = jimdemoworker.cmd statistics.sql = statistics.sql EndProjectSection EndProject @@ -36,6 +42,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SubWorker.AndyDemo", "SubWo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SchedulingPractice.SubWorkerRunner", "SchedulingPractice.SubWorkerRunner\SchedulingPractice.SubWorkerRunner.csproj", "{5D349423-56A0-4E03-A59F-7D1AF95B78E7}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SubWorker.JimDemo", "SubWorker.JimDemo\SubWorker.JimDemo.csproj", "{8CCFCDE5-71A0-4935-8B69-9CAB71931065}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -86,6 +94,10 @@ Global {5D349423-56A0-4E03-A59F-7D1AF95B78E7}.Debug|Any CPU.Build.0 = Debug|Any CPU {5D349423-56A0-4E03-A59F-7D1AF95B78E7}.Release|Any CPU.ActiveCfg = Release|Any CPU {5D349423-56A0-4E03-A59F-7D1AF95B78E7}.Release|Any CPU.Build.0 = Release|Any CPU + {8CCFCDE5-71A0-4935-8B69-9CAB71931065}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8CCFCDE5-71A0-4935-8B69-9CAB71931065}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8CCFCDE5-71A0-4935-8B69-9CAB71931065}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8CCFCDE5-71A0-4935-8B69-9CAB71931065}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -99,6 +111,7 @@ Global {7D80EF21-E6C8-46EC-8179-67D328B15335} = {5A225F28-B864-4306-B0C7-83D9CBDABF5B} {32F4B1E1-4A5B-4695-9BCD-1A76F8566420} = {5A225F28-B864-4306-B0C7-83D9CBDABF5B} {29711E67-24F9-4736-AAC8-BBE6831A4DEF} = {5A225F28-B864-4306-B0C7-83D9CBDABF5B} + {8CCFCDE5-71A0-4935-8B69-9CAB71931065} = {5A225F28-B864-4306-B0C7-83D9CBDABF5B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {43B102A2-F68E-4926-9EAA-6763FDDEF0B4} diff --git a/SubWorker.JimDemo/JimSubWorkerBackgroundService.cs b/SubWorker.JimDemo/JimSubWorkerBackgroundService.cs new file mode 100644 index 0000000..0c77835 --- /dev/null +++ b/SubWorker.JimDemo/JimSubWorkerBackgroundService.cs @@ -0,0 +1,81 @@ +using Microsoft.Extensions.Hosting; +using SchedulingPractice.Core; +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace SubWorker.JimDemo +{ + public class JimSubWorkerBackgroundService : BackgroundService + { + private BlockingCollection _queue = new BlockingCollection(); + protected async override Task ExecuteAsync(CancellationToken stoppingToken) + { + await Task.Delay(1); + List tasks = new List(); + for (int i = 0; i < 5; i++) + { + Task task = Task.Run(() => Worker()); + tasks.Add(task); + } + + Stopwatch timer = new Stopwatch(); + + using (JobsRepo repo = new JobsRepo()) + { + while (stoppingToken.IsCancellationRequested == false) + { + timer.Restart(); + Console.WriteLine($"[T: {Thread.CurrentThread.ManagedThreadId}] fetch available jobs from repository..."); + + foreach (var job in repo.GetReadyJobs(JobSettings.MinPrepareTime)) + { + if (stoppingToken.IsCancellationRequested == false) + { + if (repo.GetJob(job.Id).State == 0) + { + if (repo.AcquireJobLock(job.Id)) + { + if (job.RunAt > DateTime.Now) + { + await Task.Delay(job.RunAt - DateTime.Now); + } + _queue.Add(job); + } + } + } + } + + if (stoppingToken.IsCancellationRequested == false) + { + if(JobSettings.MinPrepareTime > timer.Elapsed) + { + await Task.Delay((int)Math.Max((JobSettings.MinPrepareTime - timer.Elapsed).TotalMilliseconds, 0), stoppingToken); + } + } + } + _queue.CompleteAdding(); + Task.WaitAll(tasks.ToArray()); + } + Console.WriteLine($"[T: {Thread.CurrentThread.ManagedThreadId}] shutdown background services..."); + } + private void Worker() + { + using (JobsRepo repo = new JobsRepo()) + { + foreach (var job in this._queue.GetConsumingEnumerable()) + { + repo.ProcessLockedJob(job.Id); + Console.WriteLine($"[T: {Thread.CurrentThread.ManagedThreadId}] process job({job.Id}) with delay {(DateTime.Now - job.RunAt).TotalMilliseconds} msec..."); + } + Console.WriteLine($"[T: {Thread.CurrentThread.ManagedThreadId}] process worker thread was terminated..."); + } + } + } +} diff --git a/SubWorker.JimDemo/Program.cs b/SubWorker.JimDemo/Program.cs new file mode 100644 index 0000000..5decd91 --- /dev/null +++ b/SubWorker.JimDemo/Program.cs @@ -0,0 +1,84 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace SubWorker.JimDemo +{ + class Program + { + static void Main(string[] args) + { + var host = new HostBuilder() + .ConfigureServices((context, services) => + { + services.AddHostedService(); + }) + .Build(); + + using (host) + { + host.Start(); + host.WaitForShutdown(); + } + } + } +} +/* <<< Best Performance : 1 Process >>> +Jobs Scheduling Metrics: + +--(action count)---------------------------------------------- +- CREATE: 1767 +- ACQUIRE_SUCCESS: 1767 +- ACQUIRE_FAILURE: 0 +- COMPLETE: 1767 +- QUERYJOB: 1767 +- QUERYLIST: 66 + +--(state count)---------------------------------------------- +- COUNT(CREATE): 0 +- COUNT(LOCK): 0 +- COUNT(COMPLETE): 1767 + +--(statistics)---------------------------------------------- +- DELAY(Average): 189 +- DELAY(Stdev): 113.67526669485 + +--(test result)---------------------------------------------- +- Complete Job: True, 1767 / 1767 +- Delay Too Long: 0 +- Fail Job: True, 0 + +--(benchmark score)---------------------------------------------- +- Exec Cost Score: 8367 (querylist x 100 + acquire-failure x 10 + queryjob x 1) +- Efficient Score: 302.68 (average + stdev) +*/ +/* <<< High Availability : 5 Process >>> +Jobs Scheduling Metrics: + +--(action count)---------------------------------------------- +- CREATE: 1752 +- ACQUIRE_SUCCESS: 1752 +- ACQUIRE_FAILURE: 1598 +- COMPLETE: 1752 +- QUERYJOB: 6069 +- QUERYLIST: 314 + +--(state count)---------------------------------------------- +- COUNT(CREATE): 0 +- COUNT(LOCK): 0 +- COUNT(COMPLETE): 1752 + +--(statistics)---------------------------------------------- +- DELAY(Average): 141 +- DELAY(Stdev): 134.610298136809 + +--(test result)---------------------------------------------- +- Complete Job: True, 1752 / 1752 +- Delay Too Long: 0 +- Fail Job: True, 0 + +--(benchmark score)---------------------------------------------- +- Exec Cost Score: 53449 (querylist x 100 + acquire-failure x 10 + queryjob x 1) +- Efficient Score: 275.61 (average + stdev) + +*/ diff --git a/SubWorker.JimDemo/SubWorker.JimDemo.csproj b/SubWorker.JimDemo/SubWorker.JimDemo.csproj new file mode 100644 index 0000000..15e9084 --- /dev/null +++ b/SubWorker.JimDemo/SubWorker.JimDemo.csproj @@ -0,0 +1,15 @@ + + + + Exe + netcoreapp2.2 + + + + + + + + + +