From 57014bc9e8f45f09dfbe2fbe47274c0f486a7732 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 28 Oct 2021 21:07:34 +0200 Subject: [PATCH 01/92] Prepare next version --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 49913e8..3e295b7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,13 +4,13 @@ image: - Visual Studio 2017 # version format -version: 1.0.1.{build} +version: 1.0.2.{build} # you can use {branch} name in version format too # version: 1.0.{build}-{branch} environment: - rc_version: 1.0.1-RC{build} - base_version: 1.0.1 + rc_version: 1.0.2-RC{build} + base_version: 1.0.2 # branches to build branches: From a5b18f01355155397a1e554250f5b7f91a5f0390 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 28 Oct 2021 21:54:36 +0200 Subject: [PATCH 02/92] AddBroadcast with default storage --- .../BroadcastServiceCollectionExtensions.cs | 19 +++++++++++++++++++ .../Broadcast.AspNetCore.Test/Startup.cs | 3 ++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Broadcast.Dashboard/BroadcastServiceCollectionExtensions.cs b/src/Broadcast.Dashboard/BroadcastServiceCollectionExtensions.cs index 734d4f2..7b03472 100644 --- a/src/Broadcast.Dashboard/BroadcastServiceCollectionExtensions.cs +++ b/src/Broadcast.Dashboard/BroadcastServiceCollectionExtensions.cs @@ -10,8 +10,27 @@ namespace Broadcast { + /// + /// Extensions for + /// public static class BroadcastServiceCollectionExtensions { + /// + /// Add with a default for storing delayed tasks + /// + /// + /// + public static IServiceCollection AddBroadcast(this IServiceCollection services) + { + return services.AddBroadcast(c => c.UseTaskStore(new TaskStore())); + } + + /// + /// Add to the services + /// + /// + /// + /// public static IServiceCollection AddBroadcast(this IServiceCollection services, Action config) { var serverSetup = new ServerSetup(); diff --git a/src/Tests/Broadcast.AspNetCore.Test/Startup.cs b/src/Tests/Broadcast.AspNetCore.Test/Startup.cs index 8dfc070..452dee1 100644 --- a/src/Tests/Broadcast.AspNetCore.Test/Startup.cs +++ b/src/Tests/Broadcast.AspNetCore.Test/Startup.cs @@ -30,7 +30,8 @@ public void ConfigureServices(IServiceCollection services) #if REDIS services.AddBroadcast(c => c.UseRedisStorage("localhost:6379")); #else - services.AddBroadcast(c => c.UseTaskStore(new TaskStore())); + //services.AddBroadcast(c => c.UseTaskStore(new TaskStore())); + services.AddBroadcast(); #endif } From b46153249a3501693bb86b53246163652817f920 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 28 Oct 2021 22:32:16 +0200 Subject: [PATCH 03/92] Rename BackgroundTaskClient to BackgroundTask --- docs/changelog.md | 10 +- .../AppBuilderExtensions.cs | 2 +- .../BroadcastApplicationBuilderExtensions.cs | 2 +- src/Broadcast/BackgroundTask.cs | 132 ++++++++++++++++++ src/Broadcast/BackgroundTaskClient.cs | 81 ++--------- src/Tests/Broadcast.AspNet.Test/Startup.cs | 4 +- .../Controllers/HomeController.cs | 18 +-- ...tApiTests.cs => BackgroundTaskApiTests.cs} | 86 ++++++------ .../Api/TaskServerClientApiTests.cs | 20 +-- ...BackgroundTaskClientTaskGenerationTests.cs | 14 +- .../TaskServerClientTaskGenerationTests.cs | 6 +- .../Api/BackgroundTaskClientApiTests.cs | 78 +++++------ .../Api/TaskServerClientApiTests.cs | 40 +++--- .../Clients/BackgroundTaskClientTests.cs | 52 ------- .../Clients/BackgroundTaskTests.cs | 52 +++++++ .../Clients/TaskServerClientTests.cs | 22 +-- ...s => BackgroundTaskTaskGenerationTests.cs} | 14 +- .../TaskServerClientTaskGenerationTests.cs | 6 +- 18 files changed, 359 insertions(+), 280 deletions(-) create mode 100644 src/Broadcast/BackgroundTask.cs rename src/Tests/Broadcast.Integration.Test/Api/{BackgroundTaskClientApiTests.cs => BackgroundTaskApiTests.cs} (64%) delete mode 100644 src/Tests/Broadcast.Test/Clients/BackgroundTaskClientTests.cs create mode 100644 src/Tests/Broadcast.Test/Clients/BackgroundTaskTests.cs rename src/Tests/Broadcast.Test/Composition/{BackgroundTaskClientTaskGenerationTests.cs => BackgroundTaskTaskGenerationTests.cs} (51%) diff --git a/docs/changelog.md b/docs/changelog.md index 4b09f5b..fa8375d 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -5,10 +5,8 @@ nav_order: 99 --- ## Broadcast Changelog +### vNext +- Rename BackgroundTaskClient to BackgroundTask -### 0.5.0 -* Updated the Project to a .NetStandard Library -* Renamded Parallel mode to Serial mode -* Added: Task scheduling - Execute tasks at a certain time instead of directly -* Added: Recurring task execution - Execute tasks multiple times at a desired interval -* Breaking change: The default PorcessorMode is set to Async. If a Parallel Mode is desired, the Broadcaster has to be initialized with the ProcessorMode set to Parallel. \ No newline at end of file +### v1.0.1 +* Total workover of v0.5 \ No newline at end of file diff --git a/src/Broadcast.Dashboard/AppBuilderExtensions.cs b/src/Broadcast.Dashboard/AppBuilderExtensions.cs index db9e08e..a737178 100644 --- a/src/Broadcast.Dashboard/AppBuilderExtensions.cs +++ b/src/Broadcast.Dashboard/AppBuilderExtensions.cs @@ -52,7 +52,7 @@ public static IAppBuilder UseBroadcastServer(this IAppBuilder builder, Action new BroadcastingClient(store)); + BackgroundTask.Setup(() => new BroadcastingClient(store)); return builder; } diff --git a/src/Broadcast.Dashboard/BroadcastApplicationBuilderExtensions.cs b/src/Broadcast.Dashboard/BroadcastApplicationBuilderExtensions.cs index a87b21f..b1122ab 100644 --- a/src/Broadcast.Dashboard/BroadcastApplicationBuilderExtensions.cs +++ b/src/Broadcast.Dashboard/BroadcastApplicationBuilderExtensions.cs @@ -34,7 +34,7 @@ public static IApplicationBuilder UseBroadcastServer(this IApplicationBuilder ap var server = new Broadcaster(storage, processor, scheduler, options); - BackgroundTaskClient.Setup(() => new BroadcastingClient(storage)); + BackgroundTask.Setup(() => new BroadcastingClient(storage)); //lifetime.ApplicationStopping.Register(() => server.SendStop()); lifetime.ApplicationStopped.Register(() => server.Dispose()); diff --git a/src/Broadcast/BackgroundTask.cs b/src/Broadcast/BackgroundTask.cs new file mode 100644 index 0000000..6234cbb --- /dev/null +++ b/src/Broadcast/BackgroundTask.cs @@ -0,0 +1,132 @@ +using Broadcast.Composition; +using System; +using System.Linq.Expressions; +using Broadcast.Configuration; +using Broadcast.EventSourcing; +using Broadcast.Server; +using Broadcast.Storage; + +namespace Broadcast +{ + /// + /// Executes Tasks in the background or on a TaskServer or cluster + /// + public class BackgroundTask + { + private static readonly ItemFactory ItemFactory = new ItemFactory(() => new BroadcastingClient()); + + /// + /// Gets the default instance of the + /// + public static IBroadcastingClient Client => ItemFactory.Factory(); + + /// + /// Setup a new instance for the default . + /// Setup with null to reset to the default + /// + /// + public static void Setup(Func setup) + { + ItemFactory.Factory = setup; + } + + /// + /// Create or update a recurring task. + /// The name of the Recurring Task is generated based on the . + /// If multiple Recurring Tasks have the same signature, this could cause some confusion + /// + /// + /// + /// The Id of the task. This is not the same as the name of the RecurringTask + public static string Recurring(Expression expression, TimeSpan time) + => Recurring(null, expression, time); + + /// + /// Create or update a recurring task. + /// Recurring Tasks are referenced by the name. + /// + /// Unitque name of the recurring Task + /// + /// + /// The Id of the task. This is not the same as the name of the RecurringTask + public static string Recurring(string name, Expression expression, TimeSpan time) + { + var task = TaskFactory.CreateTask(expression); + task.Time = time; + task.IsRecurring = true; + + if (!string.IsNullOrEmpty(name)) + { + task.Name = name; + } + + // check if the recurring task is already registered + var existing = Client.Store.Storage(s => s.Get(new Storage.StorageKey($"tasks:recurring:{task.Name}"))); + if (existing != null) + { + // update the existing recurring and the task by setting the id of the old task + // this way all properties get overridden with th enew values + task.Id = existing.ReferenceId; + } + + // add the task to the store + // the store will propagate the task to the registered servers + Client.Enqueue(task); + + return task.Id; + } + + /// + /// Adds a scheduled task + /// + /// + /// + /// The Id of the task + public static string Schedule(Expression expression, TimeSpan time) + { + var task = TaskFactory.CreateTask(expression); + task.Time = time; + + Client.Enqueue(task); + + return task.Id; + } + + /// + /// Process a task + /// + /// + /// The Id of the task + public static string Send(Expression expression) + { + var task = TaskFactory.CreateTask(expression); + + Client.Enqueue(task); + + return task.Id; + } + + /// + /// Deltete a from the Executionpipeline. + /// If a task is allready in the state of the delete will be ignored. + /// + /// + public static void DeleteTask(string taskId) + { + Client.Store.Delete(taskId); + } + + /// + /// Delete a recurring task with the associated task execution + /// + /// The name of the recurring Task + public static void DeleteRecurringTask(string name) + { + var recurring = Client.Store.Storage(s => s.Get(new Storage.StorageKey($"tasks:recurring:{name}"))); + if (recurring != null) + { + Client.Store.Delete(recurring.ReferenceId); + } + } + } +} diff --git a/src/Broadcast/BackgroundTaskClient.cs b/src/Broadcast/BackgroundTaskClient.cs index 23c3005..2a4dfd3 100644 --- a/src/Broadcast/BackgroundTaskClient.cs +++ b/src/Broadcast/BackgroundTaskClient.cs @@ -1,10 +1,6 @@ -using Broadcast.Composition; +using Broadcast.EventSourcing; using System; using System.Linq.Expressions; -using Broadcast.Configuration; -using Broadcast.EventSourcing; -using Broadcast.Server; -using Broadcast.Storage; namespace Broadcast { @@ -13,22 +9,14 @@ namespace Broadcast /// public class BackgroundTaskClient { - private static readonly ItemFactory ItemFactory = new ItemFactory(() => new BroadcastingClient()); - - /// - /// Gets the default instance of the - /// - public static IBroadcastingClient Client => ItemFactory.Factory(); - /// /// Setup a new instance for the default . /// Setup with null to reset to the default /// /// - public static void Setup(Func setup) - { - ItemFactory.Factory = setup; - } + [Obsolete("Use BackgroundTask")] + public static void Setup(Func setup) + => BackgroundTask.Setup(setup); /// /// Create or update a recurring task. @@ -38,6 +26,7 @@ public static void Setup(Func setup) /// /// /// The Id of the task. This is not the same as the name of the RecurringTask + [Obsolete("Use BackgroundTask")] public static string Recurring(Expression expression, TimeSpan time) => Recurring(null, expression, time); @@ -49,32 +38,9 @@ public static string Recurring(Expression expression, TimeSpan time) /// /// /// The Id of the task. This is not the same as the name of the RecurringTask + [Obsolete("Use BackgroundTask")] public static string Recurring(string name, Expression expression, TimeSpan time) - { - var task = TaskFactory.CreateTask(expression); - task.Time = time; - task.IsRecurring = true; - - if (!string.IsNullOrEmpty(name)) - { - task.Name = name; - } - - // check if the recurring task is already registered - var existing = Client.Store.Storage(s => s.Get(new Storage.StorageKey($"tasks:recurring:{task.Name}"))); - if (existing != null) - { - // update the existing recurring and the task by setting the id of the old task - // this way all properties get overridden with th enew values - task.Id = existing.ReferenceId; - } - - // add the task to the store - // the store will propagate the task to the registered servers - Client.Enqueue(task); - - return task.Id; - } + => BackgroundTask.Recurring(name, expression, time); /// /// Adds a scheduled task @@ -82,51 +48,34 @@ public static string Recurring(string name, Expression expression, TimeS /// /// /// The Id of the task + [Obsolete("Use BackgroundTask")] public static string Schedule(Expression expression, TimeSpan time) - { - var task = TaskFactory.CreateTask(expression); - task.Time = time; - - Client.Enqueue(task); - - return task.Id; - } + => BackgroundTask.Schedule(expression, time); /// /// Process a task /// /// /// The Id of the task + [Obsolete("Use BackgroundTask")] public static string Send(Expression expression) - { - var task = TaskFactory.CreateTask(expression); - - Client.Enqueue(task); - - return task.Id; - } + => BackgroundTask.Send(expression); /// /// Deltete a from the Executionpipeline. /// If a task is allready in the state of the delete will be ignored. /// /// + [Obsolete("Use BackgroundTask")] public static void DeleteTask(string taskId) - { - Client.Store.Delete(taskId); - } + => BackgroundTask.DeleteTask(taskId); /// /// Delete a recurring task with the associated task execution /// /// The name of the recurring Task + [Obsolete("Use BackgroundTask")] public static void DeleteRecurringTask(string name) - { - var recurring = Client.Store.Storage(s => s.Get(new Storage.StorageKey($"tasks:recurring:{name}"))); - if (recurring != null) - { - Client.Store.Delete(recurring.ReferenceId); - } - } + => BackgroundTask.DeleteRecurringTask(name); } } diff --git a/src/Tests/Broadcast.AspNet.Test/Startup.cs b/src/Tests/Broadcast.AspNet.Test/Startup.cs index dc88c8e..f5ec978 100644 --- a/src/Tests/Broadcast.AspNet.Test/Startup.cs +++ b/src/Tests/Broadcast.AspNet.Test/Startup.cs @@ -24,8 +24,8 @@ public void Configuration(IAppBuilder app) }); app.UseBroadcastDashboard(); - BackgroundTaskClient.Recurring(() => Trace.WriteLine("Broadcast Server task set from Startup"), TimeSpan.FromSeconds(20)); - BackgroundTaskClient.Recurring("Action", () => Trace.WriteLine("Broadcast task set from Startup"), TimeSpan.FromSeconds(30)); + BackgroundTask.Recurring(() => Trace.WriteLine("Broadcast Server task set from Startup"), TimeSpan.FromSeconds(20)); + BackgroundTask.Recurring("Action", () => Trace.WriteLine("Broadcast task set from Startup"), TimeSpan.FromSeconds(30)); } } } \ No newline at end of file diff --git a/src/Tests/Broadcast.AspNetCore.Test/Controllers/HomeController.cs b/src/Tests/Broadcast.AspNetCore.Test/Controllers/HomeController.cs index 48d9fe6..02e10c7 100644 --- a/src/Tests/Broadcast.AspNetCore.Test/Controllers/HomeController.cs +++ b/src/Tests/Broadcast.AspNetCore.Test/Controllers/HomeController.cs @@ -26,21 +26,21 @@ public IActionResult Index() public IActionResult CreateLongTaskInvalidInvocation() { - BackgroundTaskClient.Send(() => LongRunningMethod()); + BackgroundTask.Send(() => LongRunningMethod()); return Redirect("Index"); } public IActionResult CreateLongTask() { var service = new TaskService(); - BackgroundTaskClient.Send(() => service.LongRunningMethod()); + BackgroundTask.Send(() => service.LongRunningMethod()); return Redirect("Index"); } public IActionResult CreateFailingTask() { var service = new TaskService(); - BackgroundTaskClient.Send(() => service.FailingMethod()); + BackgroundTask.Send(() => service.FailingMethod()); return Redirect("Index"); } @@ -49,7 +49,7 @@ public IActionResult MultipleTask() var service = new TaskService(); for(var i = 1;i<=10;i++) { - BackgroundTaskClient.Send(() => service.OutputMethod(i)); + BackgroundTask.Send(() => service.OutputMethod(i)); } return Redirect("Index"); } @@ -57,7 +57,7 @@ public IActionResult MultipleTask() public IActionResult ScheduleTask() { var service = new TaskService(); - BackgroundTaskClient.Schedule(() => service.Schedule(), TimeSpan.FromSeconds(15)); + BackgroundTask.Schedule(() => service.Schedule(), TimeSpan.FromSeconds(15)); return Redirect("Index"); } @@ -68,11 +68,11 @@ public IActionResult RcurringTask() var random = new Random(); if(random.Next(4) < 2) { - BackgroundTaskClient.Recurring("recurring", () => service.Recurring(DateTime.Now.ToString("o")), TimeSpan.FromSeconds(15)); + BackgroundTask.Recurring("recurring", () => service.Recurring(DateTime.Now.ToString("o")), TimeSpan.FromSeconds(15)); } else { - BackgroundTaskClient.Recurring("recurring", () => service.Recurring2(DateTime.Now.ToString("o")), TimeSpan.FromSeconds(15)); + BackgroundTask.Recurring("recurring", () => service.Recurring2(DateTime.Now.ToString("o")), TimeSpan.FromSeconds(15)); } return Redirect("Index"); @@ -81,8 +81,8 @@ public IActionResult RcurringTask() public IActionResult DeleteTask() { var service = new TaskService(); - var taskId = BackgroundTaskClient.Schedule(() => service.Schedule(), TimeSpan.FromSeconds(15)); - BackgroundTaskClient.DeleteTask(taskId); + var taskId = BackgroundTask.Schedule(() => service.Schedule(), TimeSpan.FromSeconds(15)); + BackgroundTask.DeleteTask(taskId); return Redirect("Index"); } diff --git a/src/Tests/Broadcast.Integration.Test/Api/BackgroundTaskClientApiTests.cs b/src/Tests/Broadcast.Integration.Test/Api/BackgroundTaskApiTests.cs similarity index 64% rename from src/Tests/Broadcast.Integration.Test/Api/BackgroundTaskClientApiTests.cs rename to src/Tests/Broadcast.Integration.Test/Api/BackgroundTaskApiTests.cs index d2ea612..c676a13 100644 --- a/src/Tests/Broadcast.Integration.Test/Api/BackgroundTaskClientApiTests.cs +++ b/src/Tests/Broadcast.Integration.Test/Api/BackgroundTaskApiTests.cs @@ -14,7 +14,7 @@ namespace Broadcast.Integration.Test.Api [SingleThreaded] [Explicit] [Category("Integration")] - public class BackgroundTaskClientApiTests + public class BackgroundTaskApiTests { [SetUp] public void Setup() @@ -31,33 +31,33 @@ public void TearDown() } [Test] - public void BackgroundTaskClient_Api_Send_StaticTrace() + public void BackgroundTask_Api_Send_StaticTrace() { // execute a static method // serializeable - BackgroundTaskClient.Send(() => Trace.WriteLine("test")); + BackgroundTask.Send(() => Trace.WriteLine("test")); BroadcastServer.Server.WaitAll(); Assert.AreEqual(1, BroadcastServer.Server.GetProcessedTasks().Count()); } [Test] - public void BackgroundTaskClient_Api_Send_Method() + public void BackgroundTask_Api_Send_Method() { // execute a local method // serializeable - BackgroundTaskClient.Send(() => TestMethod(1)); + BackgroundTask.Send(() => TestMethod(1)); BroadcastServer.Server.WaitAll(); Assert.AreEqual(1, BroadcastServer.Server.GetProcessedTasks().Count()); } [Test] - public void BackgroundTaskClient_Api_Send_GenericMethod() + public void BackgroundTask_Api_Send_GenericMethod() { // execute a generic method // serializeable - BackgroundTaskClient.Send(() => GenericMethod(1)); + BackgroundTask.Send(() => GenericMethod(1)); BroadcastServer.Server.WaitAll(); Assert.AreEqual(1, BroadcastServer.Server.GetProcessedTasks().Count()); @@ -67,11 +67,11 @@ public void BackgroundTaskClient_Api_Send_GenericMethod() [Test] - public void BackgroundTaskClient_Api_Schedule_StaticTrace() + public void BackgroundTask_Api_Schedule_StaticTrace() { // execute a static method // serializeable - BackgroundTaskClient.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(1)); + BackgroundTask.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(1)); Task.Delay(1500).Wait(); @@ -79,11 +79,11 @@ public void BackgroundTaskClient_Api_Schedule_StaticTrace() } [Test] - public void BackgroundTaskClient_Api_Schedule_Method() + public void BackgroundTask_Api_Schedule_Method() { // execute a local method // serializeable - BackgroundTaskClient.Schedule(() => TestMethod(1), TimeSpan.FromSeconds(1)); + BackgroundTask.Schedule(() => TestMethod(1), TimeSpan.FromSeconds(1)); Task.Delay(1500).Wait(); @@ -91,11 +91,11 @@ public void BackgroundTaskClient_Api_Schedule_Method() } [Test] - public void BackgroundTaskClient_Api_Schedule_GenericMethod() + public void BackgroundTask_Api_Schedule_GenericMethod() { // execute a generic method // serializeable - BackgroundTaskClient.Schedule(() => GenericMethod(1), TimeSpan.FromSeconds(1)); + BackgroundTask.Schedule(() => GenericMethod(1), TimeSpan.FromSeconds(1)); Task.Delay(1500).Wait(); @@ -105,11 +105,11 @@ public void BackgroundTaskClient_Api_Schedule_GenericMethod() [Test] - public void BackgroundTaskClient_Api_Recurring_StaticTrace() + public void BackgroundTask_Api_Recurring_StaticTrace() { // execute a static method // serializeable - BackgroundTaskClient.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); Task.Delay(2000).Wait(); @@ -117,11 +117,11 @@ public void BackgroundTaskClient_Api_Recurring_StaticTrace() } [Test] - public void BackgroundTaskClient_Api_Recurring_Method() + public void BackgroundTask_Api_Recurring_Method() { // execute a local method // serializeable - BackgroundTaskClient.Recurring(() => TestMethod(1), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring(() => TestMethod(1), TimeSpan.FromSeconds(0.5)); Task.Delay(2000).Wait(); @@ -129,11 +129,11 @@ public void BackgroundTaskClient_Api_Recurring_Method() } [Test] - public void BackgroundTaskClient_Api_Recurring_GenericMethod() + public void BackgroundTask_Api_Recurring_GenericMethod() { // execute a generic method // serializeable - BackgroundTaskClient.Recurring(() => GenericMethod(1), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring(() => GenericMethod(1), TimeSpan.FromSeconds(0.5)); Task.Delay(2000).Wait(); @@ -141,29 +141,29 @@ public void BackgroundTaskClient_Api_Recurring_GenericMethod() } [Test] - public void BackgroundTaskClient_Api_Recurring_Name() + public void BackgroundTask_Api_Recurring_Name() { // execute a static method // serializeable - BackgroundTaskClient.Recurring("BackgroundTaskClient_Api_Recurring", () => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring("BackgroundTask_Api_Recurring", () => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); Task.Delay(2000).Wait(); - Assert.IsTrue(BroadcastServer.Server.GetProcessedTasks().All(t => t.Name == "BackgroundTaskClient_Api_Recurring")); + Assert.IsTrue(BroadcastServer.Server.GetProcessedTasks().All(t => t.Name == "BackgroundTask_Api_Recurring")); } [Test] - public void BackgroundTaskClient_Api_Recurring_Update() + public void BackgroundTask_Api_Recurring_Update() { // execute a static method // serializeable - BackgroundTaskClient.Recurring("Updateable", () => Trace.WriteLine("test"), TimeSpan.FromSeconds(30)); + BackgroundTask.Recurring("Updateable", () => Trace.WriteLine("test"), TimeSpan.FromSeconds(30)); Task.Delay(1000).Wait(); var originalRecurring = BroadcastServer.Server.Store.Storage(s => s.Get(new StorageKey($"tasks:recurring:Updateable"))); var originalTask = BroadcastServer.Server.Store.FirstOrDefault(t => t.Id == originalRecurring["ReferenceId"].ToString()); - BackgroundTaskClient.Recurring("Updateable", () => Trace.WriteLine("succeeded"), TimeSpan.FromSeconds(30)); + BackgroundTask.Recurring("Updateable", () => Trace.WriteLine("succeeded"), TimeSpan.FromSeconds(30)); Task.Delay(1000).Wait(); var updatedRecurring = BroadcastServer.Server.Store.Storage(s => s.Get(new StorageKey($"tasks:recurring:Updateable"))); @@ -174,17 +174,17 @@ public void BackgroundTaskClient_Api_Recurring_Update() [Test] - public void BackgroundTaskClient_Api_Recurring_Update_MethodChanged() + public void BackgroundTask_Api_Recurring_Update_MethodChanged() { // execute a static method // serializeable - BackgroundTaskClient.Recurring("Updateable", () => Trace.WriteLine("test"), TimeSpan.FromSeconds(30)); + BackgroundTask.Recurring("Updateable", () => Trace.WriteLine("test"), TimeSpan.FromSeconds(30)); Task.Delay(1000).Wait(); var originalRecurring = BroadcastServer.Server.Store.Storage(s => s.Get(new StorageKey($"tasks:recurring:Updateable"))); var originalTask = BroadcastServer.Server.Store.FirstOrDefault(t => t.Id == originalRecurring["ReferenceId"].ToString()) as BroadcastTask; - BackgroundTaskClient.Recurring("Updateable", () => Trace.WriteLine("succeeded"), TimeSpan.FromSeconds(30)); + BackgroundTask.Recurring("Updateable", () => Trace.WriteLine("succeeded"), TimeSpan.FromSeconds(30)); Task.Delay(1000).Wait(); var updatedRecurring = BroadcastServer.Server.Store.Storage(s => s.Get(new StorageKey($"tasks:recurring:Updateable"))); @@ -194,17 +194,17 @@ public void BackgroundTaskClient_Api_Recurring_Update_MethodChanged() } [Test] - public void BackgroundTaskClient_Api_Recurring_Update_SameId_Task() + public void BackgroundTask_Api_Recurring_Update_SameId_Task() { // execute a static method // serializeable - BackgroundTaskClient.Recurring("Updateable", () => Trace.WriteLine("test"), TimeSpan.FromSeconds(30)); + BackgroundTask.Recurring("Updateable", () => Trace.WriteLine("test"), TimeSpan.FromSeconds(30)); Task.Delay(1000).Wait(); var originalRecurring = BroadcastServer.Server.Store.Storage(s => s.Get(new StorageKey($"tasks:recurring:Updateable"))); var originalTask = BroadcastServer.Server.Store.FirstOrDefault(t => t.Id == originalRecurring["ReferenceId"].ToString()); - BackgroundTaskClient.Recurring("Updateable", () => Trace.WriteLine("succeeded"), TimeSpan.FromSeconds(30)); + BackgroundTask.Recurring("Updateable", () => Trace.WriteLine("succeeded"), TimeSpan.FromSeconds(30)); Task.Delay(1000).Wait(); var updatedRecurring = BroadcastServer.Server.Store.Storage(s => s.Get(new StorageKey($"tasks:recurring:Updateable"))); @@ -214,16 +214,16 @@ public void BackgroundTaskClient_Api_Recurring_Update_SameId_Task() } [Test] - public void BackgroundTaskClient_Api_Recurring_Update_SameId_Reference() + public void BackgroundTask_Api_Recurring_Update_SameId_Reference() { // execute a static method // serializeable - BackgroundTaskClient.Recurring("Updateable", () => Trace.WriteLine("test"), TimeSpan.FromSeconds(30)); + BackgroundTask.Recurring("Updateable", () => Trace.WriteLine("test"), TimeSpan.FromSeconds(30)); Task.Delay(1000).Wait(); var originalRecurring = BroadcastServer.Server.Store.Storage(s => s.Get(new StorageKey($"tasks:recurring:Updateable"))); - BackgroundTaskClient.Recurring("Updateable", () => Trace.WriteLine("succeeded"), TimeSpan.FromSeconds(30)); + BackgroundTask.Recurring("Updateable", () => Trace.WriteLine("succeeded"), TimeSpan.FromSeconds(30)); Task.Delay(1000).Wait(); var updatedRecurring = BroadcastServer.Server.Store.Storage(s => s.Get(new StorageKey($"tasks:recurring:Updateable"))); @@ -233,37 +233,37 @@ public void BackgroundTaskClient_Api_Recurring_Update_SameId_Reference() [Test] - public void BackgroundTaskClient_Api_Delete() + public void BackgroundTask_Api_Delete() { // execute a generic method // serializeable - var id = BackgroundTaskClient.Schedule(() => GenericMethod(1), TimeSpan.FromSeconds(15)); - BackgroundTaskClient.DeleteTask(id); + var id = BackgroundTask.Schedule(() => GenericMethod(1), TimeSpan.FromSeconds(15)); + BackgroundTask.DeleteTask(id); Assert.That(BroadcastServer.Server.Store.Count(t => t.State == TaskState.Deleted), Is.GreaterThan(0)); Assert.That(BroadcastServer.Server.Store.All(t => t.State == TaskState.Deleted)); } [Test] - public void BackgroundTaskClient_Api_DeleteRecurring() + public void BackgroundTask_Api_DeleteRecurring() { // execute a generic method // serializeable - BackgroundTaskClient.Recurring("recurring_delete", () => GenericMethod(1), TimeSpan.FromSeconds(15)); - BackgroundTaskClient.DeleteRecurringTask("recurring_delete"); + BackgroundTask.Recurring("recurring_delete", () => GenericMethod(1), TimeSpan.FromSeconds(15)); + BackgroundTask.DeleteRecurringTask("recurring_delete"); Assert.IsNull(BroadcastServer.Server.Store.Storage(s => s.Get(new StorageKey($"tasks:recurring:recurring_delete")))); } [Test] - public void BackgroundTaskClient_Api_DeleteRecurring_ReferencedTask_Deleted() + public void BackgroundTask_Api_DeleteRecurring_ReferencedTask_Deleted() { // execute a generic method // serializeable - BackgroundTaskClient.Recurring("recurring_delete", () => GenericMethod(1), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring("recurring_delete", () => GenericMethod(1), TimeSpan.FromSeconds(0.5)); Task.Delay(2000).Wait(); - BackgroundTaskClient.DeleteRecurringTask("recurring_delete"); + BackgroundTask.DeleteRecurringTask("recurring_delete"); Assert.That(BroadcastServer.Server.Store.Count(t => t.State == TaskState.Deleted), Is.GreaterThanOrEqualTo(1)); } diff --git a/src/Tests/Broadcast.Integration.Test/Api/TaskServerClientApiTests.cs b/src/Tests/Broadcast.Integration.Test/Api/TaskServerClientApiTests.cs index 2f920a6..4ed208a 100644 --- a/src/Tests/Broadcast.Integration.Test/Api/TaskServerClientApiTests.cs +++ b/src/Tests/Broadcast.Integration.Test/Api/TaskServerClientApiTests.cs @@ -34,7 +34,7 @@ public void TaskServerClient_Api_Send_StaticTrace() { // execute a static method // serializeable - BackgroundTaskClient.Send(() => Trace.WriteLine("test")); + BackgroundTask.Send(() => Trace.WriteLine("test")); BroadcastServer.Server.WaitAll(); Assert.AreEqual(1, BroadcastServer.Server.GetProcessedTasks().Count()); @@ -45,7 +45,7 @@ public void TaskServerClient_Api_Send_Method() { // execute a local method // serializeable - BackgroundTaskClient.Send(() => TestMethod(1)); + BackgroundTask.Send(() => TestMethod(1)); BroadcastServer.Server.WaitAll(); Assert.AreEqual(1, BroadcastServer.Server.GetProcessedTasks().Count()); @@ -56,7 +56,7 @@ public void TaskServerClient_Api_Send_GenericMethod() { // execute a generic method // serializeable - BackgroundTaskClient.Send(() => GenericMethod(1)); + BackgroundTask.Send(() => GenericMethod(1)); BroadcastServer.Server.WaitAll(); Assert.AreEqual(1, BroadcastServer.Server.GetProcessedTasks().Count()); @@ -75,7 +75,7 @@ public void TaskServerClient_Api_Schedule_StaticTrace() { // execute a static method // serializeable - BackgroundTaskClient.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(1)); + BackgroundTask.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(1)); Task.Delay(1500).Wait(); @@ -87,7 +87,7 @@ public void TaskServerClient_Api_Schedule_Method() { // execute a local method // serializeable - BackgroundTaskClient.Schedule(() => TestMethod(1), TimeSpan.FromSeconds(1)); + BackgroundTask.Schedule(() => TestMethod(1), TimeSpan.FromSeconds(1)); Task.Delay(1500).Wait(); @@ -99,7 +99,7 @@ public void TaskServerClient_Api_Schedule_GenericMethod() { // execute a generic method // serializeable - BackgroundTaskClient.Schedule(() => GenericMethod(1), TimeSpan.FromSeconds(1)); + BackgroundTask.Schedule(() => GenericMethod(1), TimeSpan.FromSeconds(1)); Task.Delay(1500).Wait(); @@ -113,7 +113,7 @@ public void TaskServerClient_Api_Recurring_StaticTrace() { // execute a static method // serializeable - BackgroundTaskClient.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); Task.Delay(2000).Wait(); @@ -125,7 +125,7 @@ public void TaskServerClient_Api_Recurring_Method() { // execute a local method // serializeable - BackgroundTaskClient.Recurring(() => TestMethod(1), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring(() => TestMethod(1), TimeSpan.FromSeconds(0.5)); Task.Delay(2000).Wait(); @@ -137,7 +137,7 @@ public void TaskServerClient_Api_Recurring_GenericMethod() { // execute a generic method // serializeable - BackgroundTaskClient.Recurring(() => GenericMethod(1), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring(() => GenericMethod(1), TimeSpan.FromSeconds(0.5)); Task.Delay(2000).Wait(); @@ -149,7 +149,7 @@ public void TaskServerClient_Api_Recurring_Name() { // execute a generic method // serializeable - BackgroundTaskClient.Recurring("TaskServerClient_Api_Recurring", () => GenericMethod(1), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring("TaskServerClient_Api_Recurring", () => GenericMethod(1), TimeSpan.FromSeconds(0.5)); Task.Delay(2000).Wait(); diff --git a/src/Tests/Broadcast.Integration.Test/Composition/BackgroundTaskClientTaskGenerationTests.cs b/src/Tests/Broadcast.Integration.Test/Composition/BackgroundTaskClientTaskGenerationTests.cs index 191bbd0..7e95950 100644 --- a/src/Tests/Broadcast.Integration.Test/Composition/BackgroundTaskClientTaskGenerationTests.cs +++ b/src/Tests/Broadcast.Integration.Test/Composition/BackgroundTaskClientTaskGenerationTests.cs @@ -13,7 +13,7 @@ namespace Broadcast.Integration.Test.Composition [SingleThreaded] [Explicit] [Category("Integration")] - public class BackgroundTaskClientTaskGenerationTests + public class BackgroundTaskTaskGenerationTests { [SetUp] public void Setup() @@ -30,21 +30,21 @@ public void TearDown() } [Test] - public void BackgroundTaskClient_TaskGeneration_Send() + public void BackgroundTask_TaskGeneration_Send() { // execute a static method // serializeable - BackgroundTaskClient.Send(() => Trace.WriteLine("test")); + BackgroundTask.Send(() => Trace.WriteLine("test")); Assert.IsAssignableFrom(BroadcastServer.Server.Store.Single()); } [Test] - public void BackgroundTaskClient_TaskGeneration_Schedule() + public void BackgroundTask_TaskGeneration_Schedule() { // execute a static method // serializeable - BackgroundTaskClient.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); Task.Delay(1000).Wait(); @@ -52,11 +52,11 @@ public void BackgroundTaskClient_TaskGeneration_Schedule() } [Test] - public void BackgroundTaskClient_TaskGeneration_Recurring() + public void BackgroundTask_TaskGeneration_Recurring() { // execute a static method // serializeable - BackgroundTaskClient.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); Task.Delay(1000).Wait(); diff --git a/src/Tests/Broadcast.Integration.Test/Composition/TaskServerClientTaskGenerationTests.cs b/src/Tests/Broadcast.Integration.Test/Composition/TaskServerClientTaskGenerationTests.cs index 6283017..43565a3 100644 --- a/src/Tests/Broadcast.Integration.Test/Composition/TaskServerClientTaskGenerationTests.cs +++ b/src/Tests/Broadcast.Integration.Test/Composition/TaskServerClientTaskGenerationTests.cs @@ -34,7 +34,7 @@ public void TaskServerClient_TaskGeneration_Send() { // execute a static method // serializeable - BackgroundTaskClient.Send(() => Trace.WriteLine("test")); + BackgroundTask.Send(() => Trace.WriteLine("test")); Assert.IsAssignableFrom(BroadcastServer.Server.Store.Single()); } @@ -44,7 +44,7 @@ public void TaskServerClient_TaskGeneration_Schedule() { // execute a static method // serializeable - BackgroundTaskClient.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); //Thread.Sleep(TimeSpan.FromSeconds(1)); Task.Delay(1000).Wait(); @@ -57,7 +57,7 @@ public void TaskServerClient_TaskGeneration_Recurring() { // execute a static method // serializeable - BackgroundTaskClient.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); //Thread.Sleep(TimeSpan.FromSeconds(1)); Task.Delay(1000).Wait(); diff --git a/src/Tests/Broadcast.Test/Api/BackgroundTaskClientApiTests.cs b/src/Tests/Broadcast.Test/Api/BackgroundTaskClientApiTests.cs index 9bfc110..b75709d 100644 --- a/src/Tests/Broadcast.Test/Api/BackgroundTaskClientApiTests.cs +++ b/src/Tests/Broadcast.Test/Api/BackgroundTaskClientApiTests.cs @@ -13,7 +13,7 @@ namespace Broadcast.Test.Api { [SingleThreaded] - public class BackgroundTaskClientApiTests + public class BackgroundTaskApiTests { private Mock _processor; private Mock _scheduler; @@ -35,121 +35,121 @@ public void Setup() [TearDown] public void Teardown() { - BackgroundTaskClient.Setup(null); + BackgroundTask.Setup(null); } [Test] - public void BackgroundTaskClient_Api_Send_StaticTrace_Process() + public void BackgroundTask_Api_Send_StaticTrace_Process() { // execute a static method // serializeable - BackgroundTaskClient.Send(() => Trace.WriteLine("test")); + BackgroundTask.Send(() => Trace.WriteLine("test")); - BackgroundTaskClient.Client.Store.WaitAll(); + BackgroundTask.Client.Store.WaitAll(); _processor.Verify(exp => exp.Process(It.IsAny()), Times.Once); } [Test] - public void BackgroundTaskClient_Api_Send_StaticTrace_StoreAdd() + public void BackgroundTask_Api_Send_StaticTrace_StoreAdd() { - BackgroundTaskClient.Setup(() => new BroadcastingClient(_store.Object)); + BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); // execute a static method // serializeable - BackgroundTaskClient.Send(() => Trace.WriteLine("test")); + BackgroundTask.Send(() => Trace.WriteLine("test")); _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); } [Test] - public void BackgroundTaskClient_Api_Send_Method_Process() + public void BackgroundTask_Api_Send_Method_Process() { // execute a local method // serializeable - BackgroundTaskClient.Send(() => TestMethod(1)); + BackgroundTask.Send(() => TestMethod(1)); - BackgroundTaskClient.Client.Store.WaitAll(); + BackgroundTask.Client.Store.WaitAll(); _processor.Verify(exp => exp.Process(It.IsAny()), Times.Once); } [Test] - public void BackgroundTaskClient_Api_Send_Method_StoreAdd() + public void BackgroundTask_Api_Send_Method_StoreAdd() { - BackgroundTaskClient.Setup(() => new BroadcastingClient(_store.Object)); + BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); // execute a local method // serializeable - BackgroundTaskClient.Send(() => TestMethod(1)); + BackgroundTask.Send(() => TestMethod(1)); _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); } [Test] - public void BackgroundTaskClient_Api_Send_GenericMethod_Process() + public void BackgroundTask_Api_Send_GenericMethod_Process() { // execute a generic method // serializeable - BackgroundTaskClient.Send(() => GenericMethod(1)); + BackgroundTask.Send(() => GenericMethod(1)); - BackgroundTaskClient.Client.Store.WaitAll(); + BackgroundTask.Client.Store.WaitAll(); _processor.Verify(exp => exp.Process(It.IsAny()), Times.Once); } [Test] - public void BackgroundTaskClient_Api_Send_GenericMethod_StoreAdd() + public void BackgroundTask_Api_Send_GenericMethod_StoreAdd() { - BackgroundTaskClient.Setup(() => new BroadcastingClient(_store.Object)); + BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); // execute a generic method // serializeable - BackgroundTaskClient.Send(() => GenericMethod(1)); + BackgroundTask.Send(() => GenericMethod(1)); _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); } [Test] - public void BackgroundTaskClient_Api_Schedule_StaticTrace() + public void BackgroundTask_Api_Schedule_StaticTrace() { // execute a static method // serializeable - BackgroundTaskClient.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(1)); - BackgroundTaskClient.Client.Store.WaitAll(); + BackgroundTask.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(1)); + BackgroundTask.Client.Store.WaitAll(); _scheduler.Verify(exp => exp.Enqueue(It.IsAny(), It.IsAny>(), It.IsAny()), Times.Once); } [Test] - public void BackgroundTaskClient_Api_Schedule_Method() + public void BackgroundTask_Api_Schedule_Method() { // execute a local method // serializeable - BackgroundTaskClient.Schedule(() => TestMethod(1), TimeSpan.FromSeconds(1)); - BackgroundTaskClient.Client.Store.WaitAll(); + BackgroundTask.Schedule(() => TestMethod(1), TimeSpan.FromSeconds(1)); + BackgroundTask.Client.Store.WaitAll(); _scheduler.Verify(exp => exp.Enqueue(It.IsAny(), It.IsAny>(), It.IsAny()), Times.Once); } [Test] - public void BackgroundTaskClient_Api_Schedule_GenericMethod() + public void BackgroundTask_Api_Schedule_GenericMethod() { // execute a generic method // serializeable - BackgroundTaskClient.Schedule(() => GenericMethod(1), TimeSpan.FromSeconds(1)); - BackgroundTaskClient.Client.Store.WaitAll(); + BackgroundTask.Schedule(() => GenericMethod(1), TimeSpan.FromSeconds(1)); + BackgroundTask.Client.Store.WaitAll(); _scheduler.Verify(exp => exp.Enqueue(It.IsAny(), It.IsAny>(), It.IsAny()), Times.Once); } [Test] - public void BackgroundTaskClient_Api_Recurring_StaticTrace() + public void BackgroundTask_Api_Recurring_StaticTrace() { // execute a static method // serializeable - BackgroundTaskClient.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); Task.Delay(1000).Wait(); @@ -157,11 +157,11 @@ public void BackgroundTaskClient_Api_Recurring_StaticTrace() } [Test] - public void BackgroundTaskClient_Api_Recurring_Method() + public void BackgroundTask_Api_Recurring_Method() { // execute a local method // serializeable - BackgroundTaskClient.Recurring(() => TestMethod(1), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring(() => TestMethod(1), TimeSpan.FromSeconds(0.5)); Task.Delay(1000).Wait(); @@ -169,11 +169,11 @@ public void BackgroundTaskClient_Api_Recurring_Method() } [Test] - public void BackgroundTaskClient_Api_Recurring_GenericMethod() + public void BackgroundTask_Api_Recurring_GenericMethod() { // execute a generic method // serializeable - BackgroundTaskClient.Recurring(() => GenericMethod(1), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring(() => GenericMethod(1), TimeSpan.FromSeconds(0.5)); Task.Delay(1000).Wait(); @@ -181,16 +181,16 @@ public void BackgroundTaskClient_Api_Recurring_GenericMethod() } [Test] - public void BackgroundTaskClient_Api_Recurring_Name() + public void BackgroundTask_Api_Recurring_Name() { - BackgroundTaskClient.Setup(() => new BroadcastingClient(_store.Object)); + BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); // execute a local method // serializeable - BackgroundTaskClient.Recurring("BackgroundTaskClient_Api_Recurring", () => TestMethod(1), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring("BackgroundTask_Api_Recurring", () => TestMethod(1), TimeSpan.FromSeconds(0.5)); Task.Delay(1000).Wait(); - _store.Verify(exp => exp.Add(It.Is(t => t.Name == "BackgroundTaskClient_Api_Recurring")), Times.Once); + _store.Verify(exp => exp.Add(It.Is(t => t.Name == "BackgroundTask_Api_Recurring")), Times.Once); } diff --git a/src/Tests/Broadcast.Test/Api/TaskServerClientApiTests.cs b/src/Tests/Broadcast.Test/Api/TaskServerClientApiTests.cs index 618154c..1cb1286 100644 --- a/src/Tests/Broadcast.Test/Api/TaskServerClientApiTests.cs +++ b/src/Tests/Broadcast.Test/Api/TaskServerClientApiTests.cs @@ -36,7 +36,7 @@ public void Setup() [TearDown] public void Teardown() { - BackgroundTaskClient.Setup(null); + BackgroundTask.Setup(null); } [Test] @@ -44,9 +44,9 @@ public void TaskServerClient_Api_Send_StaticTrace_Process() { // execute a static method // serializeable - BackgroundTaskClient.Send(() => Trace.WriteLine("test")); + BackgroundTask.Send(() => Trace.WriteLine("test")); - BackgroundTaskClient.Client.Store.WaitAll(); + BackgroundTask.Client.Store.WaitAll(); _processor.Verify(exp => exp.Process(It.IsAny()), Times.Once); } @@ -54,11 +54,11 @@ public void TaskServerClient_Api_Send_StaticTrace_Process() [Test] public void TaskServerClient_Api_Send_StaticTrace_StoreAdd() { - BackgroundTaskClient.Setup(() => new BroadcastingClient(_store.Object)); + BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); // execute a static method // serializeable - BackgroundTaskClient.Send(() => Trace.WriteLine("test")); + BackgroundTask.Send(() => Trace.WriteLine("test")); _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); } @@ -68,9 +68,9 @@ public void TaskServerClient_Api_Send_Method_Process() { // execute a local method // serializeable - BackgroundTaskClient.Send(() => TestMethod(1)); + BackgroundTask.Send(() => TestMethod(1)); - BackgroundTaskClient.Client.Store.WaitAll(); + BackgroundTask.Client.Store.WaitAll(); _processor.Verify(exp => exp.Process(It.IsAny()), Times.Once); } @@ -78,11 +78,11 @@ public void TaskServerClient_Api_Send_Method_Process() [Test] public void TaskServerClient_Api_Send_Method_StoreAdd() { - BackgroundTaskClient.Setup(() => new BroadcastingClient(_store.Object)); + BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); // execute a local method // serializeable - BackgroundTaskClient.Send(() => TestMethod(1)); + BackgroundTask.Send(() => TestMethod(1)); _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); } @@ -92,9 +92,9 @@ public void TaskServerClient_Api_Send_GenericMethod_Process() { // execute a generic method // serializeable - BackgroundTaskClient.Send(() => GenericMethod(1)); + BackgroundTask.Send(() => GenericMethod(1)); - BackgroundTaskClient.Client.Store.WaitAll(); + BackgroundTask.Client.Store.WaitAll(); _processor.Verify(exp => exp.Process(It.IsAny()), Times.Once); } @@ -102,11 +102,11 @@ public void TaskServerClient_Api_Send_GenericMethod_Process() [Test] public void TaskServerClient_Api_Send_GenericMethod_StoreAdd() { - BackgroundTaskClient.Setup(() => new BroadcastingClient(_store.Object)); + BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); // execute a generic method // serializeable - BackgroundTaskClient.Send(() => GenericMethod(1)); + BackgroundTask.Send(() => GenericMethod(1)); _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); } @@ -124,7 +124,7 @@ public void TaskServerClient_Api_Schedule_StaticTrace() { // execute a static method // serializeable - BackgroundTaskClient.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(1)); + BackgroundTask.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(1)); _scheduler.Verify(exp => exp.Enqueue(It.IsAny(), It.IsAny>(), It.IsAny()), Times.Once); } @@ -134,7 +134,7 @@ public void TaskServerClient_Api_Schedule_Method() { // execute a local method // serializeable - BackgroundTaskClient.Schedule(() => TestMethod(1), TimeSpan.FromSeconds(1)); + BackgroundTask.Schedule(() => TestMethod(1), TimeSpan.FromSeconds(1)); _scheduler.Verify(exp => exp.Enqueue(It.IsAny(), It.IsAny>(), It.IsAny()), Times.Once); } @@ -144,7 +144,7 @@ public void TaskServerClient_Api_Schedule_GenericMethod() { // execute a generic method // serializeable - BackgroundTaskClient.Schedule(() => GenericMethod(1), TimeSpan.FromSeconds(1)); + BackgroundTask.Schedule(() => GenericMethod(1), TimeSpan.FromSeconds(1)); _scheduler.Verify(exp => exp.Enqueue(It.IsAny(), It.IsAny>(), It.IsAny()), Times.Once); } @@ -159,7 +159,7 @@ public void TaskServerClient_Api_Recurring_StaticTrace() // execute a static method // serializeable - BackgroundTaskClient.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); Task.Delay(2000).Wait(); @@ -171,7 +171,7 @@ public void TaskServerClient_Api_Recurring_Method() { // execute a local method // serializeable - BackgroundTaskClient.Recurring(() => TestMethod(1), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring(() => TestMethod(1), TimeSpan.FromSeconds(0.5)); Task.Delay(1000).Wait(); @@ -183,7 +183,7 @@ public void TaskServerClient_Api_Recurring_GenericMethod() { // execute a generic method // serializeable - BackgroundTaskClient.Recurring(() => GenericMethod(1), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring(() => GenericMethod(1), TimeSpan.FromSeconds(0.5)); Task.Delay(1000).Wait(); @@ -198,7 +198,7 @@ public void TaskServerClient_Api_Recurring_Name() // execute a static method // serializeable - BackgroundTaskClient.Recurring("TaskServerClient_Api_Recurring", () => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); + BackgroundTask.Recurring("TaskServerClient_Api_Recurring", () => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); Task.Delay(2000).Wait(); diff --git a/src/Tests/Broadcast.Test/Clients/BackgroundTaskClientTests.cs b/src/Tests/Broadcast.Test/Clients/BackgroundTaskClientTests.cs deleted file mode 100644 index c4e7c40..0000000 --- a/src/Tests/Broadcast.Test/Clients/BackgroundTaskClientTests.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using NUnit.Framework; - -namespace Broadcast.Test.Clients -{ - public class BackgroundTaskClientTests - { - [SetUp] - public void Setup() - { - // set to null to reset - BackgroundTaskClient.Setup(null); - } - - [Test] - public void BackgroundTaskClient_BroadcastingClient_Default() - { - Assert.IsNotNull(BackgroundTaskClient.Client); - } - - [Test] - public void BackgroundTaskClient_BroadcastingClient_Default_Setup() - { - var def = BackgroundTaskClient.Client; - BackgroundTaskClient.Setup(() => new BroadcastingClient()); - - Assert.AreNotSame(def, BackgroundTaskClient.Client); - } - - [Test] - public void BackgroundTaskClient_BroadcastingClient_Default_Setup_Reset() - { - var def = BackgroundTaskClient.Client; - BackgroundTaskClient.Setup(() => new BroadcastingClient()); - - // set to null to reset - BackgroundTaskClient.Setup(null); - - Assert.AreSame(def, BackgroundTaskClient.Client); - } - - [Test] - public void BackgroundTaskClient_BroadcastingClient_Default_Setup_Singleton() - { - BackgroundTaskClient.Setup(() => new BroadcastingClient()); - - Assert.AreSame(BackgroundTaskClient.Client, BackgroundTaskClient.Client); - } - } -} diff --git a/src/Tests/Broadcast.Test/Clients/BackgroundTaskTests.cs b/src/Tests/Broadcast.Test/Clients/BackgroundTaskTests.cs new file mode 100644 index 0000000..8780ffb --- /dev/null +++ b/src/Tests/Broadcast.Test/Clients/BackgroundTaskTests.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Text; +using NUnit.Framework; + +namespace Broadcast.Test.Clients +{ + public class BackgroundTaskTests + { + [SetUp] + public void Setup() + { + // set to null to reset + BackgroundTask.Setup(null); + } + + [Test] + public void BackgroundTask_BroadcastingClient_Default() + { + Assert.IsNotNull(BackgroundTask.Client); + } + + [Test] + public void BackgroundTask_BroadcastingClient_Default_Setup() + { + var def = BackgroundTask.Client; + BackgroundTask.Setup(() => new BroadcastingClient()); + + Assert.AreNotSame(def, BackgroundTask.Client); + } + + [Test] + public void BackgroundTask_BroadcastingClient_Default_Setup_Reset() + { + var def = BackgroundTask.Client; + BackgroundTask.Setup(() => new BroadcastingClient()); + + // set to null to reset + BackgroundTask.Setup(null); + + Assert.AreSame(def, BackgroundTask.Client); + } + + [Test] + public void BackgroundTask_BroadcastingClient_Default_Setup_Singleton() + { + BackgroundTask.Setup(() => new BroadcastingClient()); + + Assert.AreSame(BackgroundTask.Client, BackgroundTask.Client); + } + } +} diff --git a/src/Tests/Broadcast.Test/Clients/TaskServerClientTests.cs b/src/Tests/Broadcast.Test/Clients/TaskServerClientTests.cs index c25a4dc..2040229 100644 --- a/src/Tests/Broadcast.Test/Clients/TaskServerClientTests.cs +++ b/src/Tests/Broadcast.Test/Clients/TaskServerClientTests.cs @@ -11,42 +11,42 @@ public class TaskServerClientTests public void Setup() { // set to null to reset - BackgroundTaskClient.Setup(null); + BackgroundTask.Setup(null); } [Test] public void TaskServerClient_BroadcastingClient_Default() { - Assert.IsNotNull(BackgroundTaskClient.Client); + Assert.IsNotNull(BackgroundTask.Client); } [Test] public void TaskServerClient_BroadcastingClient_Default_Setup() { - var def = BackgroundTaskClient.Client; - BackgroundTaskClient.Setup(() => new BroadcastingClient()); + var def = BackgroundTask.Client; + BackgroundTask.Setup(() => new BroadcastingClient()); - Assert.AreNotSame(def, BackgroundTaskClient.Client); + Assert.AreNotSame(def, BackgroundTask.Client); } [Test] public void TaskServerClient_BroadcastingClient_Default_Setup_Reset() { - var def = BackgroundTaskClient.Client; - BackgroundTaskClient.Setup(() => new BroadcastingClient()); + var def = BackgroundTask.Client; + BackgroundTask.Setup(() => new BroadcastingClient()); // set to null to reset - BackgroundTaskClient.Setup(null); + BackgroundTask.Setup(null); - Assert.AreSame(def, BackgroundTaskClient.Client); + Assert.AreSame(def, BackgroundTask.Client); } [Test] public void TaskServerClient_BroadcastingClient_Default_Setup_Singleton() { - BackgroundTaskClient.Setup(() => new BroadcastingClient()); + BackgroundTask.Setup(() => new BroadcastingClient()); - Assert.AreSame(BackgroundTaskClient.Client, BackgroundTaskClient.Client); + Assert.AreSame(BackgroundTask.Client, BackgroundTask.Client); } } } diff --git a/src/Tests/Broadcast.Test/Composition/BackgroundTaskClientTaskGenerationTests.cs b/src/Tests/Broadcast.Test/Composition/BackgroundTaskTaskGenerationTests.cs similarity index 51% rename from src/Tests/Broadcast.Test/Composition/BackgroundTaskClientTaskGenerationTests.cs rename to src/Tests/Broadcast.Test/Composition/BackgroundTaskTaskGenerationTests.cs index 67c099a..2e4cdaa 100644 --- a/src/Tests/Broadcast.Test/Composition/BackgroundTaskClientTaskGenerationTests.cs +++ b/src/Tests/Broadcast.Test/Composition/BackgroundTaskTaskGenerationTests.cs @@ -10,36 +10,36 @@ namespace Broadcast.Test.Composition { - public class BackgroundTaskClientTaskGenerationTests + public class BackgroundTaskTaskGenerationTests { [Test] - public void BackgroundTaskClient_TaskGeneration_Recurring_Id() + public void BackgroundTask_TaskGeneration_Recurring_Id() { BroadcastServer.Setup(s => { }); // execute a static method // serializeable - Assert.IsNotEmpty(BackgroundTaskClient.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5))); + Assert.IsNotEmpty(BackgroundTask.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5))); } [Test] - public void BackgroundTaskClient_TaskGeneration_Schedule_Id() + public void BackgroundTask_TaskGeneration_Schedule_Id() { BroadcastServer.Setup(s => { }); // execute a static method // serializeable - Assert.IsNotEmpty(BackgroundTaskClient.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5))); + Assert.IsNotEmpty(BackgroundTask.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5))); } [Test] - public void BackgroundTaskClient_TaskGeneration_Send_Id() + public void BackgroundTask_TaskGeneration_Send_Id() { BroadcastServer.Setup(s => { }); // execute a static method // serializeable - Assert.IsNotEmpty(BackgroundTaskClient.Send(() => Trace.WriteLine("test"))); + Assert.IsNotEmpty(BackgroundTask.Send(() => Trace.WriteLine("test"))); } } } diff --git a/src/Tests/Broadcast.Test/Composition/TaskServerClientTaskGenerationTests.cs b/src/Tests/Broadcast.Test/Composition/TaskServerClientTaskGenerationTests.cs index 8a114b5..09d0385 100644 --- a/src/Tests/Broadcast.Test/Composition/TaskServerClientTaskGenerationTests.cs +++ b/src/Tests/Broadcast.Test/Composition/TaskServerClientTaskGenerationTests.cs @@ -18,7 +18,7 @@ public void TaskServerClient_TaskGeneration_Recurring_Id() // execute a static method // serializeable - Assert.IsNotEmpty(BackgroundTaskClient.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5))); + Assert.IsNotEmpty(BackgroundTask.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5))); } [Test] @@ -28,7 +28,7 @@ public void TaskServerClient_TaskGeneration_Schedule_Id() // execute a static method // serializeable - Assert.IsNotEmpty(BackgroundTaskClient.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5))); + Assert.IsNotEmpty(BackgroundTask.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5))); } [Test] @@ -38,7 +38,7 @@ public void TaskServerClient_TaskGeneration_Send_Id() // execute a static method // serializeable - Assert.IsNotEmpty(BackgroundTaskClient.Send(() => Trace.WriteLine("test"))); + Assert.IsNotEmpty(BackgroundTask.Send(() => Trace.WriteLine("test"))); } } } From 61596aa750c2078e7fe40993e06df76555689980 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Fri, 29 Oct 2021 14:26:26 +0200 Subject: [PATCH 04/92] Remove Serverpropagations from storage --- .../BroadcastServiceCollectionExtensions.cs | 2 +- src/Broadcast/Broadcaster.cs | 12 ++++- src/Broadcast/BroadcasterExtensions.cs | 3 +- src/Broadcast/EventSourcing/TaskStore.cs | 29 +++++++++++- src/Broadcast/ITaskStore.cs | 6 +++ .../Controllers/HomeController.cs | 1 + .../Broadcast.AspNetCore.Test/Startup.cs | 3 ++ .../EventSourcing/TaskStoreTests.cs | 47 +++++++++++++++---- 8 files changed, 90 insertions(+), 13 deletions(-) diff --git a/src/Broadcast.Dashboard/BroadcastServiceCollectionExtensions.cs b/src/Broadcast.Dashboard/BroadcastServiceCollectionExtensions.cs index 7b03472..f4ac891 100644 --- a/src/Broadcast.Dashboard/BroadcastServiceCollectionExtensions.cs +++ b/src/Broadcast.Dashboard/BroadcastServiceCollectionExtensions.cs @@ -16,7 +16,7 @@ namespace Broadcast public static class BroadcastServiceCollectionExtensions { /// - /// Add with a default for storing delayed tasks + /// Add with a default for managing tasks /// /// /// diff --git a/src/Broadcast/Broadcaster.cs b/src/Broadcast/Broadcaster.cs index 0d48cd7..90e6801 100644 --- a/src/Broadcast/Broadcaster.cs +++ b/src/Broadcast/Broadcaster.cs @@ -152,12 +152,22 @@ protected virtual void Dispose(bool disposing) return; } + // dispatching of tasks to the servers is done anync + // if there are tasks in the storage that are not dispatched, they will not get dispatched at all + // wait for the items in the store to be dispatched all + Store.WaitAll(); + + // unregister dispatcher so the server will not get any more tasks to process + Store.UnregisterDispatchers(_id); + Scheduler.Dispose(); + Processor.WaitAll(); Processor.Dispose(); - Store.UnregisterDispatchers(_id); _context.IsRunning = false; + Store.RemoveServer(new ServerModel { Id = _id, Name = Name }); + _logger.Write($"Disposed Broadcaster {_options.ServerName}:{_id}"); } } diff --git a/src/Broadcast/BroadcasterExtensions.cs b/src/Broadcast/BroadcasterExtensions.cs index 8786e41..8690e71 100644 --- a/src/Broadcast/BroadcasterExtensions.cs +++ b/src/Broadcast/BroadcasterExtensions.cs @@ -41,7 +41,8 @@ public static string Send(this IBroadcaster broadcaster, Expression acti } /// - /// Schedules a new task. The task will be executed at the time passed + /// Schedules a new task. The task will be executed at the time that is given as parameter. + /// Schedueld Tasks only get executed if the is still running. If a is disposed or closed, all scheduled tasks are lost. /// /// /// The task to execute diff --git a/src/Broadcast/EventSourcing/TaskStore.cs b/src/Broadcast/EventSourcing/TaskStore.cs index d5d1e6e..fccf7d6 100644 --- a/src/Broadcast/EventSourcing/TaskStore.cs +++ b/src/Broadcast/EventSourcing/TaskStore.cs @@ -93,7 +93,16 @@ public TaskStore(Options options, IStorage storage) /// /// Gets a enumeration of all registered servers /// - public IEnumerable Servers => _registeredServers.Values; + public IEnumerable Servers + { + get + { + lock (_registeredServers) + { + return _registeredServers.Values; + } + } + } /// /// Gets a that is used to wait for the event to be set. @@ -252,10 +261,28 @@ public void PropagateServer(ServerModel server) foreach (var key in deadServers) { _registeredServers.Remove(key); + _storage.Delete(new StorageKey($"server:{server.Name}:{server.Id}")); } } } + /// + /// Remove a server from the TaskStore. + /// + /// + public void RemoveServer(ServerModel server) + { + lock (_registeredServers) + { + if (_registeredServers.ContainsKey(server.Id)) + { + _registeredServers.Remove(server.Id); + } + + _storage.Delete(new StorageKey($"server:{server.Name}:{server.Id}")); + } + } + /// /// Wait for all enqueued Tasks to be passed to the dispatchers /// diff --git a/src/Broadcast/ITaskStore.cs b/src/Broadcast/ITaskStore.cs index 11f630b..cda75b7 100644 --- a/src/Broadcast/ITaskStore.cs +++ b/src/Broadcast/ITaskStore.cs @@ -78,6 +78,12 @@ public interface ITaskStore : IEnumerable /// void PropagateServer(ServerModel server); + /// + /// Remove a server from the TaskStore. + /// + /// + void RemoveServer(ServerModel server); + /// /// Wait for all enqueued Tasks to be passed to the dispatchers /// diff --git a/src/Tests/Broadcast.AspNetCore.Test/Controllers/HomeController.cs b/src/Tests/Broadcast.AspNetCore.Test/Controllers/HomeController.cs index 02e10c7..d63569e 100644 --- a/src/Tests/Broadcast.AspNetCore.Test/Controllers/HomeController.cs +++ b/src/Tests/Broadcast.AspNetCore.Test/Controllers/HomeController.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Broadcast.AspNetCore.Test.Models; +using Broadcast.EventSourcing; namespace Broadcast.AspNetCore.Test.Controllers { diff --git a/src/Tests/Broadcast.AspNetCore.Test/Startup.cs b/src/Tests/Broadcast.AspNetCore.Test/Startup.cs index 452dee1..1c42c61 100644 --- a/src/Tests/Broadcast.AspNetCore.Test/Startup.cs +++ b/src/Tests/Broadcast.AspNetCore.Test/Startup.cs @@ -15,6 +15,8 @@ namespace Broadcast.AspNetCore.Test { public class Startup { + //static Broadcaster Server; + public Startup(IConfiguration configuration) { Configuration = configuration; @@ -58,6 +60,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) ServerName = "test 1" }); + //Server = new Broadcaster(TaskStore.Default); app.UseBroadcastDashboard(); diff --git a/src/Tests/Broadcast.Test/EventSourcing/TaskStoreTests.cs b/src/Tests/Broadcast.Test/EventSourcing/TaskStoreTests.cs index 205f065..0212226 100644 --- a/src/Tests/Broadcast.Test/EventSourcing/TaskStoreTests.cs +++ b/src/Tests/Broadcast.Test/EventSourcing/TaskStoreTests.cs @@ -467,22 +467,51 @@ public void TaskStore_PropagateServer_Cleanup() Assert.IsEmpty(store.Servers); } + [Test] + public void TaskStore_RemoveServer() + { + var server = new ServerModel + { + Id = "1", + Name = "server", + Heartbeat = DateTime.Now + }; + var store = new TaskStore(); + store.PropagateServer(server); + // act + store.RemoveServer(new ServerModel + { + Id = "1", + Name = "server" + }); + Assert.IsEmpty(store.Servers); + } + [Test] + public void TaskStore_RemoveServer_DeleteFromStorage() + { + var server = new ServerModel + { + Id = "1", + Name = "server", + Heartbeat = DateTime.Now + }; + var store = new TaskStore(); + store.PropagateServer(server); + // act + store.RemoveServer(new ServerModel + { + Id = "1", + Name = "server" + }); - - - - - - - - - + Assert.IsNull(store.Storage(s => s.Get(new StorageKey("server:1:server")))); + } [Test] From db3263f0dba82ee67d480b7b7d3e4a30c1f2835b Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Fri, 29 Oct 2021 14:51:08 +0200 Subject: [PATCH 05/92] Mark BackgroundTaskClient as obsolete --- .../BroadcastApplicationBuilderExtensions.cs | 11 +++++++++-- src/Broadcast/BackgroundTask.cs | 3 ++- src/Broadcast/BackgroundTaskClient.cs | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Broadcast.Dashboard/BroadcastApplicationBuilderExtensions.cs b/src/Broadcast.Dashboard/BroadcastApplicationBuilderExtensions.cs index b1122ab..ed2513c 100644 --- a/src/Broadcast.Dashboard/BroadcastApplicationBuilderExtensions.cs +++ b/src/Broadcast.Dashboard/BroadcastApplicationBuilderExtensions.cs @@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis; using Broadcast.Configuration; using Broadcast.Dashboard; +using Broadcast.EventSourcing; using Broadcast.Processing; using Broadcast.Scheduling; using Microsoft.AspNetCore.Builder; @@ -26,7 +27,8 @@ public static IApplicationBuilder UseBroadcastServer(this IApplicationBuilder ap #else var lifetime = services.GetRequiredService(); #endif - var storage = services.GetRequiredService(); + // use TaskStore.Default if the services.AddBroadcast() is not configured + var storage = services.GetService() ?? TaskStore.Default; options ??= services.GetService() ?? new Options(); var processor = new TaskProcessor(storage, options); @@ -58,7 +60,12 @@ public static IApplicationBuilder UseBroadcastDashboard(this IApplicationBuilder DashboardOptions.Default.TemplateParameters["%(RouteBasePath)"] = pathMatch.EnsureLeadingSlash(); var routes = app.ApplicationServices.GetService() ?? Routes.RouteCollection; - var storage = app.ApplicationServices.GetRequiredService(); + var storage = app.ApplicationServices.GetService(); + if (storage == null) + { + Console.WriteLine("Could not get registered ITaskStore. Using TaskStore.Default instead"); + storage = TaskStore.Default; + } app.Map(new PathString(pathMatch), x => x.UseMiddleware(routes, storage)); diff --git a/src/Broadcast/BackgroundTask.cs b/src/Broadcast/BackgroundTask.cs index 6234cbb..c5e3b3e 100644 --- a/src/Broadcast/BackgroundTask.cs +++ b/src/Broadcast/BackgroundTask.cs @@ -9,7 +9,8 @@ namespace Broadcast { /// - /// Executes Tasks in the background or on a TaskServer or cluster + /// Executes Tasks in the background or on a TaskServer or cluster. + /// To use the BackgroundTask dispatching, there needs to be a registered Braodcaster /// public class BackgroundTask { diff --git a/src/Broadcast/BackgroundTaskClient.cs b/src/Broadcast/BackgroundTaskClient.cs index 2a4dfd3..97bec26 100644 --- a/src/Broadcast/BackgroundTaskClient.cs +++ b/src/Broadcast/BackgroundTaskClient.cs @@ -7,6 +7,7 @@ namespace Broadcast /// /// Executes Tasks in the background or on a TaskServer or cluster /// + [Obsolete("Use BackgroundTask for simpler use")] public class BackgroundTaskClient { /// From 449555199e31764110d5d8ef1f182b8d9f572f4a Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Fri, 29 Oct 2021 22:15:10 +0200 Subject: [PATCH 06/92] path to opencovr --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 60eb954..132a01c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -110,8 +110,8 @@ after_test: # to run your custom scripts instead of automatic tests test_script: # - echo This is my custom test script - - packages\OpenCover.Console.exe -register:user -targetargs:"test --logger:trx;LogFileName=results.trx /p:DebugType=full -output:"broadcaster_coverage.xml" -filter:"+[LetsDisc*]* -[Tests*]*" - - packages\codecov -f "broadcaster_coverage.xml" + - .\packages\OpenCover.Console.exe -register:user -targetargs:"test --logger:trx;LogFileName=results.trx /p:DebugType=full -output:"broadcaster_coverage.xml" -filter:"+[LetsDisc*]* -[Tests*]*" + - .\packages\codecov -f "broadcaster_coverage.xml" # to disable automatic tests #test: off From def597eefd2bcce8502ef6a8d2ec08ddbdb37217 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Fri, 29 Oct 2021 22:26:59 +0200 Subject: [PATCH 07/92] navigate to codecover --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 132a01c..f00ff9c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -110,8 +110,8 @@ after_test: # to run your custom scripts instead of automatic tests test_script: # - echo This is my custom test script - - .\packages\OpenCover.Console.exe -register:user -targetargs:"test --logger:trx;LogFileName=results.trx /p:DebugType=full -output:"broadcaster_coverage.xml" -filter:"+[LetsDisc*]* -[Tests*]*" - - .\packages\codecov -f "broadcaster_coverage.xml" + - packages\OpenCover.4.7.1221\OpenCover.Console.exe -register:user -targetargs:"test --logger:trx;LogFileName=results.trx /p:DebugType=full -output:"broadcaster_coverage.xml" -filter:"+[LetsDisc*]* -[Tests*]*" + - packages\codecov -f "broadcaster_coverage.xml" # to disable automatic tests #test: off From 0a38b655cd11be9c0a1901521409da7a2e3ae8cd Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sat, 30 Oct 2021 22:24:56 +0200 Subject: [PATCH 08/92] OpenCover without version --- appveyor.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index f00ff9c..6a5cbb7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -50,7 +50,8 @@ configuration: Release before_build: - nuget restore - - nuget install OpenCover -OutputDirectory packages -Version 4.7.1221 + - nuget install OpenCover -OutputDirectory packages -ExcludeVersion +# - nuget install OpenCover -OutputDirectory packages -Version 4.7.1221 - nuget install codecov -OutputDirectory packages build: @@ -110,7 +111,7 @@ after_test: # to run your custom scripts instead of automatic tests test_script: # - echo This is my custom test script - - packages\OpenCover.4.7.1221\OpenCover.Console.exe -register:user -targetargs:"test --logger:trx;LogFileName=results.trx /p:DebugType=full -output:"broadcaster_coverage.xml" -filter:"+[LetsDisc*]* -[Tests*]*" + - packages\OpenCover\tools\OpenCover.Console.exe -register:user -targetargs:"test --logger:trx;LogFileName=results.trx /p:DebugType=full -output:"broadcaster_coverage.xml" -filter:"+[LetsDisc*]* -[Tests*]*" - packages\codecov -f "broadcaster_coverage.xml" # to disable automatic tests #test: off From 0b74208b42929196f53135ee8214b53505c63a4a Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sat, 30 Oct 2021 22:32:18 +0200 Subject: [PATCH 09/92] Update filter for CodeCover --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 6a5cbb7..214ce53 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -111,7 +111,7 @@ after_test: # to run your custom scripts instead of automatic tests test_script: # - echo This is my custom test script - - packages\OpenCover\tools\OpenCover.Console.exe -register:user -targetargs:"test --logger:trx;LogFileName=results.trx /p:DebugType=full -output:"broadcaster_coverage.xml" -filter:"+[LetsDisc*]* -[Tests*]*" + - packages\OpenCover\tools\OpenCover.Console.exe -register:user -targetargs:"test --logger:trx;LogFileName=results.trx /p:DebugType=full -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" - packages\codecov -f "broadcaster_coverage.xml" # to disable automatic tests #test: off From f9e301cfb5e64e270bb4a72311cd1367cdc20f54 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sat, 30 Oct 2021 22:45:56 +0200 Subject: [PATCH 10/92] NUnit for OpenCover --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 214ce53..cd78135 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -50,6 +50,7 @@ configuration: Release before_build: - nuget restore + - nuget install NUnit.Console -OutputDirectory packages -ExcludeVersion - nuget install OpenCover -OutputDirectory packages -ExcludeVersion # - nuget install OpenCover -OutputDirectory packages -Version 4.7.1221 - nuget install codecov -OutputDirectory packages @@ -111,7 +112,7 @@ after_test: # to run your custom scripts instead of automatic tests test_script: # - echo This is my custom test script - - packages\OpenCover\tools\OpenCover.Console.exe -register:user -targetargs:"test --logger:trx;LogFileName=results.trx /p:DebugType=full -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" + - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.Console\tools\nunit3-console.exe" -targetargs:"test --logger:trx;LogFileName=results.trx /p:DebugType=full -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" - packages\codecov -f "broadcaster_coverage.xml" # to disable automatic tests #test: off From 8c97602ebec1fff8f65bdb9fd5fb28d3ecdff1a7 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sat, 30 Oct 2021 22:52:37 +0200 Subject: [PATCH 11/92] Nunit.ConsoleRunner --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index cd78135..f9105df 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -112,7 +112,7 @@ after_test: # to run your custom scripts instead of automatic tests test_script: # - echo This is my custom test script - - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.Console\tools\nunit3-console.exe" -targetargs:"test --logger:trx;LogFileName=results.trx /p:DebugType=full -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" + - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"test --logger:trx;LogFileName=results.trx /p:DebugType=full -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" - packages\codecov -f "broadcaster_coverage.xml" # to disable automatic tests #test: off From 6c0bf483ccf36838a715a4568d036d5f8417beac Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sun, 31 Oct 2021 07:56:11 +0100 Subject: [PATCH 12/92] Define testprojects for opencover --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index f9105df..a804e50 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -112,7 +112,7 @@ after_test: # to run your custom scripts instead of automatic tests test_script: # - echo This is my custom test script - - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"test --logger:trx;LogFileName=results.trx /p:DebugType=full -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" + - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"**\*.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" - packages\codecov -f "broadcaster_coverage.xml" # to disable automatic tests #test: off From 8ad4708c577f48423a78762c2a84281b19728e2a Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sun, 31 Oct 2021 08:02:08 +0100 Subject: [PATCH 13/92] Testproject reference --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a804e50..5df20dd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -112,7 +112,7 @@ after_test: # to run your custom scripts instead of automatic tests test_script: # - echo This is my custom test script - - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"**\*.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" + - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"src\Tests\Broadcast.Test\bin\Debug\netcoreapp3.1\Broadcast.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" - packages\codecov -f "broadcaster_coverage.xml" # to disable automatic tests #test: off From 350b59ba9c90f07b590d599d7ba3e0386860332e Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sun, 31 Oct 2021 08:04:36 +0100 Subject: [PATCH 14/92] Release build for OpenCover --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 5df20dd..3dba9da 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -112,7 +112,7 @@ after_test: # to run your custom scripts instead of automatic tests test_script: # - echo This is my custom test script - - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"src\Tests\Broadcast.Test\bin\Debug\netcoreapp3.1\Broadcast.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" + - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" - packages\codecov -f "broadcaster_coverage.xml" # to disable automatic tests #test: off From d2614658e63b7470b11c8548391db2c267eac796 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sun, 31 Oct 2021 08:12:14 +0100 Subject: [PATCH 15/92] Update opencover for dotnet core --- appveyor.yml | 3 ++- src/Broadcast/Broadcast.csproj | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 3dba9da..6a0ad2e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -112,7 +112,8 @@ after_test: # to run your custom scripts instead of automatic tests test_script: # - echo This is my custom test script - - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" +# - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" + - packages\OpenCover\tools\OpenCover.Console.Exe -target:"c:\program files\dotnet\dotnet.exe" -targetargs:"test src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -oldstyle -output:"broadcaster_coverage.xml" -filter:"+[Test*]* - packages\codecov -f "broadcaster_coverage.xml" # to disable automatic tests #test: off diff --git a/src/Broadcast/Broadcast.csproj b/src/Broadcast/Broadcast.csproj index e9c57aa..89b82ef 100644 --- a/src/Broadcast/Broadcast.csproj +++ b/src/Broadcast/Broadcast.csproj @@ -28,5 +28,8 @@ Broadcast helps implement patterns like Mediator and CQRS (Command- and Queryhan bin\Release\netstandard2.0\Broadcast.xml - + + + Full + From 42def7ae4915c9559131392d3bdebe163d36c318 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 07:02:53 +0100 Subject: [PATCH 16/92] Update nuget summary --- appveyor.yml | 2 +- src/Broadcast/Broadcast.csproj | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 6a0ad2e..4a430ec 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -114,7 +114,7 @@ test_script: # - echo This is my custom test script # - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" - packages\OpenCover\tools\OpenCover.Console.Exe -target:"c:\program files\dotnet\dotnet.exe" -targetargs:"test src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -oldstyle -output:"broadcaster_coverage.xml" -filter:"+[Test*]* - - packages\codecov -f "broadcaster_coverage.xml" + - packages\codecov\tools\codecov -f "broadcaster_coverage.xml" # to disable automatic tests #test: off diff --git a/src/Broadcast/Broadcast.csproj b/src/Broadcast/Broadcast.csproj index 89b82ef..176f4dc 100644 --- a/src/Broadcast/Broadcast.csproj +++ b/src/Broadcast/Broadcast.csproj @@ -11,10 +11,9 @@ Christian Walpen @WickedFlame 2019 Broadcast - A simple fire and forget, message broker. -Broadcast is a simple implementation for processing queued, synchronous and asynchronous tasks and notifications. -Broadcast helps implement patterns like Mediator and CQRS (Command- and Queryhandling) - Task scheduling and processing made simple + Broadcast is a simple implementation for processing and scheduling tasks in the background without blocking the main thread. + Broadcast helps implement the Mediator or CQRS (Command- and Queryhandling) patterns easily. + Simple and easy to use background task processing and message queue for .NET http://wickedflame.github.io/ Async Task processing, Task scheduler Request, Commands, Notification, Mediator, CQRS, Fire and forget 1.0.0 From 15e8c66d80bd0a4d4d49359cf90cc66b322eab2a Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 07:47:46 +0100 Subject: [PATCH 17/92] Find path to broadcaster_coverage.xml --- appveyor.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4a430ec..7bd16be 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -113,8 +113,8 @@ after_test: test_script: # - echo This is my custom test script # - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" - - packages\OpenCover\tools\OpenCover.Console.Exe -target:"c:\program files\dotnet\dotnet.exe" -targetargs:"test src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -oldstyle -output:"broadcaster_coverage.xml" -filter:"+[Test*]* - - packages\codecov\tools\codecov -f "broadcaster_coverage.xml" + - packages\OpenCover\tools\OpenCover.Console -target:"c:\program files\dotnet\dotnet.exe" -targetargs:"test src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -oldstyle -output:".\broadcaster_coverage.xml" -filter:"+[Test*]* + - packages\codecov\tools\codecov -f ".\broadcaster_coverage.xml" # to disable automatic tests #test: off @@ -129,4 +129,5 @@ artifacts: name: Broadcast.Dashboard.dll # pushing all *.nupkg files in directory - - path: '.\*.nupkg' \ No newline at end of file + - path: '.\*.nupkg' + - path: 'broadcaster_coverage.xml' \ No newline at end of file From 2c34659ebdbbd1ca4c3f9cc0d894386833986c75 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 08:08:54 +0100 Subject: [PATCH 18/92] Add coverage.xml to artifacts --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 7bd16be..89d637a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -114,7 +114,7 @@ test_script: # - echo This is my custom test script # - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" - packages\OpenCover\tools\OpenCover.Console -target:"c:\program files\dotnet\dotnet.exe" -targetargs:"test src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -oldstyle -output:".\broadcaster_coverage.xml" -filter:"+[Test*]* - - packages\codecov\tools\codecov -f ".\broadcaster_coverage.xml" +# - packages\codecov\tools\codecov -f ".\broadcaster_coverage.xml" # to disable automatic tests #test: off From f8ff0621b7e26b6d3d80489a869a1b1b67865494 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 08:21:01 +0100 Subject: [PATCH 19/92] Filter for CodeCoverage --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 89d637a..ef23889 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -113,7 +113,7 @@ after_test: test_script: # - echo This is my custom test script # - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" - - packages\OpenCover\tools\OpenCover.Console -target:"c:\program files\dotnet\dotnet.exe" -targetargs:"test src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -oldstyle -output:".\broadcaster_coverage.xml" -filter:"+[Test*]* + - packages\OpenCover\tools\OpenCover.Console -target:"c:\program files\dotnet\dotnet.exe" -targetargs:"test src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -oldstyle -output:".\broadcaster_coverage.xml" -filter:"+[Broadcast*]* # - packages\codecov\tools\codecov -f ".\broadcaster_coverage.xml" # to disable automatic tests #test: off From 018748e51a0e860dc0cae9ad0aa94782802a0826 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 08:44:15 +0100 Subject: [PATCH 20/92] try find broadcaster_coverage.xml --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index ef23889..99dd930 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -114,7 +114,7 @@ test_script: # - echo This is my custom test script # - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" - packages\OpenCover\tools\OpenCover.Console -target:"c:\program files\dotnet\dotnet.exe" -targetargs:"test src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -oldstyle -output:".\broadcaster_coverage.xml" -filter:"+[Broadcast*]* -# - packages\codecov\tools\codecov -f ".\broadcaster_coverage.xml" + - packages\codecov\tools\codecov -f broadcaster_coverage.xml # to disable automatic tests #test: off From 6173f53a4df37630441b6f891604c3c3ab5bb7b4 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 09:19:39 +0100 Subject: [PATCH 21/92] Remove codecov.yml --- codecov.yml | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index 97078de..0000000 --- a/codecov.yml +++ /dev/null @@ -1,27 +0,0 @@ -codecov: - notify: - require_ci_to_pass: true - threshold: 1% -comment: - behavior: default - layout: header,tree - require_changes: true -coverage: - precision: 2 - range: - - 70.0 - - 100.0 - round: down - status: - changes: false - patch: false - project: true -parsers: - gcov: - branch_detection: - conditional: true - loop: true - macro: false - method: false - javascript: - enable_partials: false From c84529b7a99c82c6b1be274d6d3d6dbf1ba036fe Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 09:30:50 +0100 Subject: [PATCH 22/92] Move codecov to aftertest --- appveyor.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 99dd930..7f5b8bb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -105,16 +105,17 @@ test: before_test: # - echo script1 # - ps: Write-Host "script1" - -# scripts to run after tests -after_test: - + # to run your custom scripts instead of automatic tests test_script: # - echo This is my custom test script # - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" - packages\OpenCover\tools\OpenCover.Console -target:"c:\program files\dotnet\dotnet.exe" -targetargs:"test src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -oldstyle -output:".\broadcaster_coverage.xml" -filter:"+[Broadcast*]* - - packages\codecov\tools\codecov -f broadcaster_coverage.xml + +# scripts to run after tests +after_test: + - packages\codecov\tools\codecov -f "broadcaster_coverage.xml" + # to disable automatic tests #test: off From a2b1f29106dd9cbb79384ae1c82ffe869a3b1780 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 11:32:03 +0100 Subject: [PATCH 23/92] Codecov --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 7f5b8bb..a0963dc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -114,7 +114,8 @@ test_script: # scripts to run after tests after_test: - - packages\codecov\tools\codecov -f "broadcaster_coverage.xml" + - packages\codecov\tools\codecov +# - packages\codecov\tools\codecov -f "broadcaster_coverage.xml" # to disable automatic tests #test: off From aef6c6ba1012819cddb45ee7ed3f00ed3525d7be Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 11:40:27 +0100 Subject: [PATCH 24/92] Try use PS for codecov --- appveyor.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index a0963dc..a6fbb80 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -110,11 +110,14 @@ before_test: test_script: # - echo This is my custom test script # - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" - - packages\OpenCover\tools\OpenCover.Console -target:"c:\program files\dotnet\dotnet.exe" -targetargs:"test src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -oldstyle -output:".\broadcaster_coverage.xml" -filter:"+[Broadcast*]* + - packages\OpenCover\tools\OpenCover.Console -target:"c:\program files\dotnet\dotnet.exe" -targetargs:"test src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -oldstyle -output:".\broadcast_coverage.xml" -filter:"+[Broadcast*]* # scripts to run after tests after_test: - - packages\codecov\tools\codecov + - ps: | + $env:PATH = 'C:\msys64\usr\bin;' + $env:PATH + Invoke-WebRequest -Uri 'https://codecov.io/bash' -OutFile codecov.sh + bash codecov.sh -f "broadcast_coverage.xml" # - packages\codecov\tools\codecov -f "broadcaster_coverage.xml" # to disable automatic tests @@ -132,4 +135,4 @@ artifacts: # pushing all *.nupkg files in directory - path: '.\*.nupkg' - - path: 'broadcaster_coverage.xml' \ No newline at end of file + - path: 'broadcast_coverage.xml' \ No newline at end of file From 225eac52db12cf47db0678ab202567f73160b8fa Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 12:39:11 +0100 Subject: [PATCH 25/92] Codecov --- Broadcast.sln | 1 + appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Broadcast.sln b/Broadcast.sln index 8db35b4..72c8078 100644 --- a/Broadcast.sln +++ b/Broadcast.sln @@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .travis.yml = .travis.yml appveyor.yml = appveyor.yml src\Broadcast.snk = src\Broadcast.snk + codecov.yml = codecov.yml License.txt = License.txt README.md = README.md EndProjectSection diff --git a/appveyor.yml b/appveyor.yml index a6fbb80..e8b5597 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -117,7 +117,7 @@ after_test: - ps: | $env:PATH = 'C:\msys64\usr\bin;' + $env:PATH Invoke-WebRequest -Uri 'https://codecov.io/bash' -OutFile codecov.sh - bash codecov.sh -f "broadcast_coverage.xml" + bash codecov.sh -f "broadcast_coverage.xml" -t 39773008-c39a-4103-b8ea-5cc9d2de3f01 # - packages\codecov\tools\codecov -f "broadcaster_coverage.xml" # to disable automatic tests From b62a2140b02c067ea3bdf1acba0e375e55a1492c Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 12:39:32 +0100 Subject: [PATCH 26/92] Revert "Remove codecov.yml" This reverts commit 6173f53a4df37630441b6f891604c3c3ab5bb7b4. --- codecov.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..97078de --- /dev/null +++ b/codecov.yml @@ -0,0 +1,27 @@ +codecov: + notify: + require_ci_to_pass: true + threshold: 1% +comment: + behavior: default + layout: header,tree + require_changes: true +coverage: + precision: 2 + range: + - 70.0 + - 100.0 + round: down + status: + changes: false + patch: false + project: true +parsers: + gcov: + branch_detection: + conditional: true + loop: true + macro: false + method: false + javascript: + enable_partials: false From 835c721a26a3a6f16a640fce0b6c28fecdd56566 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 12:43:21 +0100 Subject: [PATCH 27/92] CodeCov api token --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index e8b5597..a6ecf8a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -117,7 +117,7 @@ after_test: - ps: | $env:PATH = 'C:\msys64\usr\bin;' + $env:PATH Invoke-WebRequest -Uri 'https://codecov.io/bash' -OutFile codecov.sh - bash codecov.sh -f "broadcast_coverage.xml" -t 39773008-c39a-4103-b8ea-5cc9d2de3f01 + bash codecov.sh -f "broadcast_coverage.xml" -t "39773008-c39a-4103-b8ea-5cc9d2de3f01" # - packages\codecov\tools\codecov -f "broadcaster_coverage.xml" # to disable automatic tests From 879a7c005787dc7628bc1a18711124b01aafde66 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 12:52:56 +0100 Subject: [PATCH 28/92] Remove token --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a6ecf8a..a6fbb80 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -117,7 +117,7 @@ after_test: - ps: | $env:PATH = 'C:\msys64\usr\bin;' + $env:PATH Invoke-WebRequest -Uri 'https://codecov.io/bash' -OutFile codecov.sh - bash codecov.sh -f "broadcast_coverage.xml" -t "39773008-c39a-4103-b8ea-5cc9d2de3f01" + bash codecov.sh -f "broadcast_coverage.xml" # - packages\codecov\tools\codecov -f "broadcaster_coverage.xml" # to disable automatic tests From a53884de8d7e7af7f71b5fa433fccb62fe388544 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 13:17:00 +0100 Subject: [PATCH 29/92] Switch to nuget codecov --- appveyor.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index a6fbb80..c5494d0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -53,7 +53,7 @@ before_build: - nuget install NUnit.Console -OutputDirectory packages -ExcludeVersion - nuget install OpenCover -OutputDirectory packages -ExcludeVersion # - nuget install OpenCover -OutputDirectory packages -Version 4.7.1221 - - nuget install codecov -OutputDirectory packages + - nuget install codecov -OutputDirectory packages -ExcludeVersion build: parallel: true # enable MSBuild parallel builds @@ -114,11 +114,11 @@ test_script: # scripts to run after tests after_test: - - ps: | - $env:PATH = 'C:\msys64\usr\bin;' + $env:PATH - Invoke-WebRequest -Uri 'https://codecov.io/bash' -OutFile codecov.sh - bash codecov.sh -f "broadcast_coverage.xml" -# - packages\codecov\tools\codecov -f "broadcaster_coverage.xml" +# - ps: | +# $env:PATH = 'C:\msys64\usr\bin;' + $env:PATH +# Invoke-WebRequest -Uri 'https://codecov.io/bash' -OutFile codecov.sh +# bash codecov.sh -f "broadcast_coverage.xml" -t '39773008-c39a-4103-b8ea-5cc9d2de3f01' + - packages\codecov\tools\codecov -f "broadcast_coverage.xml" # to disable automatic tests #test: off From 08a1837adc97adb5cfa2a766ace258e6a6ed3e89 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 17:16:14 +0100 Subject: [PATCH 30/92] Set framework for codecov --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index c5494d0..9d5f2fa 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -53,7 +53,7 @@ before_build: - nuget install NUnit.Console -OutputDirectory packages -ExcludeVersion - nuget install OpenCover -OutputDirectory packages -ExcludeVersion # - nuget install OpenCover -OutputDirectory packages -Version 4.7.1221 - - nuget install codecov -OutputDirectory packages -ExcludeVersion + - nuget install codecov -OutputDirectory packages -ExcludeVersion -Framework netcoreapp3.1 build: parallel: true # enable MSBuild parallel builds From a5906a59e964e01a6150e3cf51a9e0f531910c0f Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 17:35:03 +0100 Subject: [PATCH 31/92] Removed codecov --- Broadcast.sln | 1 - appveyor.yml | 20 ++++---------------- codecov.yml | 27 --------------------------- 3 files changed, 4 insertions(+), 44 deletions(-) delete mode 100644 codecov.yml diff --git a/Broadcast.sln b/Broadcast.sln index 72c8078..8db35b4 100644 --- a/Broadcast.sln +++ b/Broadcast.sln @@ -12,7 +12,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .travis.yml = .travis.yml appveyor.yml = appveyor.yml src\Broadcast.snk = src\Broadcast.snk - codecov.yml = codecov.yml License.txt = License.txt README.md = README.md EndProjectSection diff --git a/appveyor.yml b/appveyor.yml index 9d5f2fa..e824c63 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -50,10 +50,6 @@ configuration: Release before_build: - nuget restore - - nuget install NUnit.Console -OutputDirectory packages -ExcludeVersion - - nuget install OpenCover -OutputDirectory packages -ExcludeVersion -# - nuget install OpenCover -OutputDirectory packages -Version 4.7.1221 - - nuget install codecov -OutputDirectory packages -ExcludeVersion -Framework netcoreapp3.1 build: parallel: true # enable MSBuild parallel builds @@ -102,23 +98,16 @@ test: # - [DAL, BL] # 2nd job # scripts to run before tests -before_test: +#before_test: # - echo script1 # - ps: Write-Host "script1" # to run your custom scripts instead of automatic tests -test_script: +#test_script: # - echo This is my custom test script -# - packages\OpenCover\tools\OpenCover.Console.exe -register:user -target:"packages\NUnit.ConsoleRunner\tools\nunit3-console.exe" -targetargs:"src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -output:"broadcaster_coverage.xml" -filter:"+[Test*]*" - - packages\OpenCover\tools\OpenCover.Console -target:"c:\program files\dotnet\dotnet.exe" -targetargs:"test src\Tests\Broadcast.Test\bin\Release\netcoreapp3.1\Broadcast.Test.dll" -oldstyle -output:".\broadcast_coverage.xml" -filter:"+[Broadcast*]* # scripts to run after tests -after_test: -# - ps: | -# $env:PATH = 'C:\msys64\usr\bin;' + $env:PATH -# Invoke-WebRequest -Uri 'https://codecov.io/bash' -OutFile codecov.sh -# bash codecov.sh -f "broadcast_coverage.xml" -t '39773008-c39a-4103-b8ea-5cc9d2de3f01' - - packages\codecov\tools\codecov -f "broadcast_coverage.xml" +#after_test: # to disable automatic tests #test: off @@ -134,5 +123,4 @@ artifacts: name: Broadcast.Dashboard.dll # pushing all *.nupkg files in directory - - path: '.\*.nupkg' - - path: 'broadcast_coverage.xml' \ No newline at end of file + - path: '.\*.nupkg' \ No newline at end of file diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index 97078de..0000000 --- a/codecov.yml +++ /dev/null @@ -1,27 +0,0 @@ -codecov: - notify: - require_ci_to_pass: true - threshold: 1% -comment: - behavior: default - layout: header,tree - require_changes: true -coverage: - precision: 2 - range: - - 70.0 - - 100.0 - round: down - status: - changes: false - patch: false - project: true -parsers: - gcov: - branch_detection: - conditional: true - loop: true - macro: false - method: false - javascript: - enable_partials: false From 5bfcd33466132e3bb2e87d4b4dd061f2e8ea82e6 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 21:34:44 +0100 Subject: [PATCH 32/92] SonarCloud for travis --- .travis.yml | 12 +++++++++++- sonar-project.properties | 12 ++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 sonar-project.properties diff --git a/.travis.yml b/.travis.yml index 3d2a714..1b98e42 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,4 +19,14 @@ install: script: - dotnet build --configuration NetCore # - dotnet test -# - dotnet test Tests/DataImporter.Tests/DataImporter.Tests.csproj \ No newline at end of file +# - dotnet test Tests/DataImporter.Tests/DataImporter.Tests.csproj + +addons: + sonarcloud: + organization: "wickedflame" + token: + secure: "$SONAR_CLOUD" # encrypted value of your token + +script: + # the following command line builds the project, runs the tests with coverage and then execute the SonarCloud analysis + - sonar-scanner \ No newline at end of file diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..056e16d --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,12 @@ +sonar.projectKey=WickedFlame_Broadcast +sonar.organization=wickedflame + +# This is the name and version displayed in the SonarCloud UI. +#sonar.projectName=Broadcast +#sonar.projectVersion=1.0 + +# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. +#sonar.sources=. + +# Encoding of the source code. Default is default system encoding +#sonar.sourceEncoding=UTF-8 \ No newline at end of file From 9c10b2ffad236398409fb3acd3ed8eedfa34f146 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 21:44:19 +0100 Subject: [PATCH 33/92] SonarCloud --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1b98e42..92f7c53 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,7 @@ addons: sonarcloud: organization: "wickedflame" token: - secure: "$SONAR_CLOUD" # encrypted value of your token + secure: "1c6083739fea417a23988ce5463194e79265f465" # encrypted value of your token script: # the following command line builds the project, runs the tests with coverage and then execute the SonarCloud analysis From 6752493630ebc53bcc7ffceeb8570a8ef92d9a0a Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 21:47:50 +0100 Subject: [PATCH 34/92] SonarCloud --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 92f7c53..49a87ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,8 +24,8 @@ script: addons: sonarcloud: organization: "wickedflame" - token: - secure: "1c6083739fea417a23988ce5463194e79265f465" # encrypted value of your token +# token: +# secure: "1c6083739fea417a23988ce5463194e79265f465" # encrypted value of your token script: # the following command line builds the project, runs the tests with coverage and then execute the SonarCloud analysis From 72bcbc37613eb003234950f60f89b9b21e3d9ddb Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 21:56:12 +0100 Subject: [PATCH 35/92] TTry set nodejs version --- .travis.yml | 3 +++ Broadcast.sln | 1 + 2 files changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 49a87ec..2f9a3b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,9 @@ mono: none #dist: xenial dotnet: 3.1.414 +node_js: + - "10" + notifications: email: # recipients: diff --git a/Broadcast.sln b/Broadcast.sln index 8db35b4..35a5422 100644 --- a/Broadcast.sln +++ b/Broadcast.sln @@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution src\Broadcast.snk = src\Broadcast.snk License.txt = License.txt README.md = README.md + sonar-project.properties = sonar-project.properties EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{7B8E8745-88B2-4319-884D-556F587570DC}" From 25e933ab25a36d204fa4a243d4a457fcd2ed101f Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 2 Nov 2021 22:05:48 +0100 Subject: [PATCH 36/92] Ignore js in sonar --- sonar-project.properties | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sonar-project.properties b/sonar-project.properties index 056e16d..e5ccc99 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -9,4 +9,7 @@ sonar.organization=wickedflame #sonar.sources=. # Encoding of the source code. Default is default system encoding -#sonar.sourceEncoding=UTF-8 \ No newline at end of file +#sonar.sourceEncoding=UTF-8 + +#sonar.exclusions=**\bin\**,**\OurProject.Web\Reports\**,**\Content\js\** +sonar.exclusions=**\bin\**,**\*.js \ No newline at end of file From 352b4cdb3a55334b1a01647870655bb10577670b Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Wed, 3 Nov 2021 07:05:05 +0100 Subject: [PATCH 37/92] Nvm install 10 --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2f9a3b8..4f162b0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,8 @@ mono: none #dist: xenial dotnet: 3.1.414 -node_js: - - "10" +#node_js: +# - "10" notifications: email: @@ -18,6 +18,8 @@ notifications: install: - dotnet restore + - nvm install 10.0.0 + - nvm use 10.0.0 script: - dotnet build --configuration NetCore From c6d8df39fec08c6006d8480cd74338b4578665c1 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Wed, 3 Nov 2021 08:23:13 +0100 Subject: [PATCH 38/92] Add sonar qualitygate badge --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index afc01c2..9b36198 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ [![NuGet Version](https://img.shields.io/nuget/v/broadcast.svg?style=for-the-badge&label=Latest)](https://www.nuget.org/packages/broadcast/) [![NuGet Version](https://img.shields.io/nuget/vpre/broadcast.svg?style=for-the-badge&label=RC)](https://www.nuget.org/packages/broadcast/) - + +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=WickedFlame_Broadcast&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=WickedFlame_Broadcast) + Simple and easy to use background task processing and message queue for .NET Broadcast is a simple implementation for processing and scheduling tasks in the background without blocking the main thread. From 8b33b9180c0faee60aa708a00da7aeeb8075818a Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Wed, 3 Nov 2021 21:32:36 +0100 Subject: [PATCH 39/92] Rename testapps --- .travis.yml | 2 +- Broadcast.sln | 6 +++--- .../App_Start/FilterConfig.cs | 0 .../App_Start/RouteConfig.cs | 0 .../Broadcast.AspNet.TestApp.csproj} | 0 .../Content/Site.css | 0 .../Content/bootstrap.min.css | 0 .../Controllers/HomeController.cs | 0 .../Global.asax | 0 .../Global.asax.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../Startup.cs | 0 .../Views/Home/Index.cshtml | 0 .../Views/Shared/Error.cshtml | 0 .../Views/Shared/_Layout.cshtml | 0 .../Views/Web.config | 0 .../Views/_ViewStart.cshtml | 0 .../Web.Debug.config | 0 .../Web.Release.config | 0 .../Web.config | 0 .../favicon.ico | Bin .../packages.config | 0 .../Broadcast.AspNetCore.TestApp.csproj} | 0 .../Controllers/DashboardApiController.cs | 0 .../Controllers/DashboardController.cs | 0 .../Controllers/HomeController.cs | 0 .../Controllers/StorageController.cs | 0 .../Models/DashboardModel.cs | 0 .../Models/ErrorViewModel.cs | 0 .../Program.cs | 0 .../Properties/launchSettings.json | 0 .../Startup.cs | 0 .../Views/Dashboard/EnqueuedTasks.cshtml | 0 .../Views/Dashboard/FailedTasks.cshtml | 0 .../Views/Dashboard/Index.cshtml | 0 .../Views/Dashboard/ProcessedTasks.cshtml | 0 .../Views/Dashboard/RecurringTasks.cshtml | 0 .../Views/Dashboard/Servers.cshtml | 0 .../Views/Dashboard/_Layout.cshtml | 0 .../Views/Home/Index.cshtml | 0 .../Views/Shared/Error.cshtml | 0 .../Views/Shared/_Layout.cshtml | 0 .../Views/Shared/_LayoutBasic.cshtml | 0 .../Views/Shared/_ValidationScriptsPartial.cshtml | 0 .../Views/Storage/Index.cshtml | 0 .../Views/Storage/Partials/_StorageKey.cshtml | 0 .../Views/_ViewImports.cshtml | 0 .../Views/_ViewStart.cshtml | 0 .../appsettings.Development.json | 0 .../appsettings.json | 0 .../compilerconfig.json | 0 .../compilerconfig.json.defaults | 0 .../wwwroot/css/Dashboard.css | 0 .../wwwroot/css/Dashboard.min.css | 0 .../wwwroot/css/Dashboard.scss | 0 .../wwwroot/css/Storage.css | 0 .../wwwroot/css/Storage.min.css | 0 .../wwwroot/css/Storage.scss | 0 .../wwwroot/css/bootstrap.min.css | 0 .../wwwroot/css/site.css | 0 .../wwwroot/css/site.min.css | 0 .../wwwroot/css/site.scss | 0 .../wwwroot/favicon.ico | Bin .../wwwroot/js/broadcast-base.js | 0 .../wwwroot/js/broadcast-dashboard.js | 0 .../wwwroot/js/broadcast-storage.js | 0 .../wwwroot/js/site.js | 0 .../Broadcast.Console.TestApp.csproj} | 0 .../Program.cs | 0 69 files changed, 4 insertions(+), 4 deletions(-) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/App_Start/FilterConfig.cs (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/App_Start/RouteConfig.cs (100%) rename src/Tests/{Broadcast.AspNet.Test/Broadcast.AspNet.Test.csproj => Broadcast.AspNet.TestApp/Broadcast.AspNet.TestApp.csproj} (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Content/Site.css (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Content/bootstrap.min.css (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Controllers/HomeController.cs (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Global.asax (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Global.asax.cs (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Properties/AssemblyInfo.cs (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Startup.cs (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Views/Home/Index.cshtml (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Views/Shared/Error.cshtml (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Views/Shared/_Layout.cshtml (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Views/Web.config (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Views/_ViewStart.cshtml (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Web.Debug.config (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Web.Release.config (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/Web.config (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/favicon.ico (100%) rename src/Tests/{Broadcast.AspNet.Test => Broadcast.AspNet.TestApp}/packages.config (100%) rename src/Tests/{Broadcast.AspNetCore.Test/Broadcast.AspNetCore.Test.csproj => Broadcast.AspNetCore.TestApp/Broadcast.AspNetCore.TestApp.csproj} (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Controllers/DashboardApiController.cs (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Controllers/DashboardController.cs (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Controllers/HomeController.cs (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Controllers/StorageController.cs (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Models/DashboardModel.cs (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Models/ErrorViewModel.cs (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Program.cs (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Properties/launchSettings.json (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Startup.cs (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/Dashboard/EnqueuedTasks.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/Dashboard/FailedTasks.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/Dashboard/Index.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/Dashboard/ProcessedTasks.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/Dashboard/RecurringTasks.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/Dashboard/Servers.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/Dashboard/_Layout.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/Home/Index.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/Shared/Error.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/Shared/_Layout.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/Shared/_LayoutBasic.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/Shared/_ValidationScriptsPartial.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/Storage/Index.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/Storage/Partials/_StorageKey.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/_ViewImports.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/Views/_ViewStart.cshtml (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/appsettings.Development.json (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/appsettings.json (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/compilerconfig.json (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/compilerconfig.json.defaults (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/css/Dashboard.css (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/css/Dashboard.min.css (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/css/Dashboard.scss (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/css/Storage.css (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/css/Storage.min.css (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/css/Storage.scss (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/css/bootstrap.min.css (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/css/site.css (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/css/site.min.css (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/css/site.scss (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/favicon.ico (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/js/broadcast-base.js (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/js/broadcast-dashboard.js (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/js/broadcast-storage.js (100%) rename src/Tests/{Broadcast.AspNetCore.Test => Broadcast.AspNetCore.TestApp}/wwwroot/js/site.js (100%) rename src/Tests/{Broadcast.Console.Test/Broadcast.Console.Test.csproj => Broadcast.Console.TestApp/Broadcast.Console.TestApp.csproj} (100%) rename src/Tests/{Broadcast.Console.Test => Broadcast.Console.TestApp}/Program.cs (100%) diff --git a/.travis.yml b/.travis.yml index 4f162b0..47c900a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ addons: sonarcloud: organization: "wickedflame" # token: -# secure: "1c6083739fea417a23988ce5463194e79265f465" # encrypted value of your token +# secure: "" # encrypted value of your token script: # the following command line builds the project, runs the tests with coverage and then execute the SonarCloud analysis diff --git a/Broadcast.sln b/Broadcast.sln index 35a5422..eb8062e 100644 --- a/Broadcast.sln +++ b/Broadcast.sln @@ -19,19 +19,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{7B8E8745-88B2-4319-884D-556F587570DC}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Broadcast.Console.Test", "src\Tests\Broadcast.Console.Test\Broadcast.Console.Test.csproj", "{D8F923B8-220A-41C1-9E5E-BDDEC71EA0BF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Broadcast.Console.TestApp", "src\Tests\Broadcast.Console.TestApp\Broadcast.Console.TestApp.csproj", "{D8F923B8-220A-41C1-9E5E-BDDEC71EA0BF}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Broadcast.Test", "src\Tests\Broadcast.Test\Broadcast.Test.csproj", "{5F4A862D-AD7C-4C5B-83FA-A920ACB8479A}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Broadcast.Integration.Test", "src\Tests\Broadcast.Integration.Test\Broadcast.Integration.Test.csproj", "{D3D96D6A-ED86-46B2-BB0A-7BAD8326DE7E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Broadcast.AspNetCore.Test", "src\Tests\Broadcast.AspNetCore.Test\Broadcast.AspNetCore.Test.csproj", "{082D5010-3136-4500-AF51-79D3153044DF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Broadcast.AspNetCore.TestApp", "src\Tests\Broadcast.AspNetCore.TestApp\Broadcast.AspNetCore.TestApp.csproj", "{082D5010-3136-4500-AF51-79D3153044DF}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Broadcast.Dashboard", "src\Broadcast.Dashboard\Broadcast.Dashboard.csproj", "{FF470A41-7608-4E25-A298-8565E92C592A}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Broadcast.Dashboard.Test", "src\Tests\Broadcast.Dashboard.Test\Broadcast.Dashboard.Test.csproj", "{CBD5AFD6-5AFC-41E5-B112-00FF3BBB485E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Broadcast.AspNet.Test", "src\Tests\Broadcast.AspNet.Test\Broadcast.AspNet.Test.csproj", "{420C8308-7468-4553-A062-E082CDCB78DB}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Broadcast.AspNet.TestApp", "src\Tests\Broadcast.AspNet.TestApp\Broadcast.AspNet.TestApp.csproj", "{420C8308-7468-4553-A062-E082CDCB78DB}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{18910F76-F1A5-43F3-9284-EFEC491C8C52}" EndProject diff --git a/src/Tests/Broadcast.AspNet.Test/App_Start/FilterConfig.cs b/src/Tests/Broadcast.AspNet.TestApp/App_Start/FilterConfig.cs similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/App_Start/FilterConfig.cs rename to src/Tests/Broadcast.AspNet.TestApp/App_Start/FilterConfig.cs diff --git a/src/Tests/Broadcast.AspNet.Test/App_Start/RouteConfig.cs b/src/Tests/Broadcast.AspNet.TestApp/App_Start/RouteConfig.cs similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/App_Start/RouteConfig.cs rename to src/Tests/Broadcast.AspNet.TestApp/App_Start/RouteConfig.cs diff --git a/src/Tests/Broadcast.AspNet.Test/Broadcast.AspNet.Test.csproj b/src/Tests/Broadcast.AspNet.TestApp/Broadcast.AspNet.TestApp.csproj similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Broadcast.AspNet.Test.csproj rename to src/Tests/Broadcast.AspNet.TestApp/Broadcast.AspNet.TestApp.csproj diff --git a/src/Tests/Broadcast.AspNet.Test/Content/Site.css b/src/Tests/Broadcast.AspNet.TestApp/Content/Site.css similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Content/Site.css rename to src/Tests/Broadcast.AspNet.TestApp/Content/Site.css diff --git a/src/Tests/Broadcast.AspNet.Test/Content/bootstrap.min.css b/src/Tests/Broadcast.AspNet.TestApp/Content/bootstrap.min.css similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Content/bootstrap.min.css rename to src/Tests/Broadcast.AspNet.TestApp/Content/bootstrap.min.css diff --git a/src/Tests/Broadcast.AspNet.Test/Controllers/HomeController.cs b/src/Tests/Broadcast.AspNet.TestApp/Controllers/HomeController.cs similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Controllers/HomeController.cs rename to src/Tests/Broadcast.AspNet.TestApp/Controllers/HomeController.cs diff --git a/src/Tests/Broadcast.AspNet.Test/Global.asax b/src/Tests/Broadcast.AspNet.TestApp/Global.asax similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Global.asax rename to src/Tests/Broadcast.AspNet.TestApp/Global.asax diff --git a/src/Tests/Broadcast.AspNet.Test/Global.asax.cs b/src/Tests/Broadcast.AspNet.TestApp/Global.asax.cs similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Global.asax.cs rename to src/Tests/Broadcast.AspNet.TestApp/Global.asax.cs diff --git a/src/Tests/Broadcast.AspNet.Test/Properties/AssemblyInfo.cs b/src/Tests/Broadcast.AspNet.TestApp/Properties/AssemblyInfo.cs similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Properties/AssemblyInfo.cs rename to src/Tests/Broadcast.AspNet.TestApp/Properties/AssemblyInfo.cs diff --git a/src/Tests/Broadcast.AspNet.Test/Startup.cs b/src/Tests/Broadcast.AspNet.TestApp/Startup.cs similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Startup.cs rename to src/Tests/Broadcast.AspNet.TestApp/Startup.cs diff --git a/src/Tests/Broadcast.AspNet.Test/Views/Home/Index.cshtml b/src/Tests/Broadcast.AspNet.TestApp/Views/Home/Index.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Views/Home/Index.cshtml rename to src/Tests/Broadcast.AspNet.TestApp/Views/Home/Index.cshtml diff --git a/src/Tests/Broadcast.AspNet.Test/Views/Shared/Error.cshtml b/src/Tests/Broadcast.AspNet.TestApp/Views/Shared/Error.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Views/Shared/Error.cshtml rename to src/Tests/Broadcast.AspNet.TestApp/Views/Shared/Error.cshtml diff --git a/src/Tests/Broadcast.AspNet.Test/Views/Shared/_Layout.cshtml b/src/Tests/Broadcast.AspNet.TestApp/Views/Shared/_Layout.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Views/Shared/_Layout.cshtml rename to src/Tests/Broadcast.AspNet.TestApp/Views/Shared/_Layout.cshtml diff --git a/src/Tests/Broadcast.AspNet.Test/Views/Web.config b/src/Tests/Broadcast.AspNet.TestApp/Views/Web.config similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Views/Web.config rename to src/Tests/Broadcast.AspNet.TestApp/Views/Web.config diff --git a/src/Tests/Broadcast.AspNet.Test/Views/_ViewStart.cshtml b/src/Tests/Broadcast.AspNet.TestApp/Views/_ViewStart.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Views/_ViewStart.cshtml rename to src/Tests/Broadcast.AspNet.TestApp/Views/_ViewStart.cshtml diff --git a/src/Tests/Broadcast.AspNet.Test/Web.Debug.config b/src/Tests/Broadcast.AspNet.TestApp/Web.Debug.config similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Web.Debug.config rename to src/Tests/Broadcast.AspNet.TestApp/Web.Debug.config diff --git a/src/Tests/Broadcast.AspNet.Test/Web.Release.config b/src/Tests/Broadcast.AspNet.TestApp/Web.Release.config similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Web.Release.config rename to src/Tests/Broadcast.AspNet.TestApp/Web.Release.config diff --git a/src/Tests/Broadcast.AspNet.Test/Web.config b/src/Tests/Broadcast.AspNet.TestApp/Web.config similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/Web.config rename to src/Tests/Broadcast.AspNet.TestApp/Web.config diff --git a/src/Tests/Broadcast.AspNet.Test/favicon.ico b/src/Tests/Broadcast.AspNet.TestApp/favicon.ico similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/favicon.ico rename to src/Tests/Broadcast.AspNet.TestApp/favicon.ico diff --git a/src/Tests/Broadcast.AspNet.Test/packages.config b/src/Tests/Broadcast.AspNet.TestApp/packages.config similarity index 100% rename from src/Tests/Broadcast.AspNet.Test/packages.config rename to src/Tests/Broadcast.AspNet.TestApp/packages.config diff --git a/src/Tests/Broadcast.AspNetCore.Test/Broadcast.AspNetCore.Test.csproj b/src/Tests/Broadcast.AspNetCore.TestApp/Broadcast.AspNetCore.TestApp.csproj similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Broadcast.AspNetCore.Test.csproj rename to src/Tests/Broadcast.AspNetCore.TestApp/Broadcast.AspNetCore.TestApp.csproj diff --git a/src/Tests/Broadcast.AspNetCore.Test/Controllers/DashboardApiController.cs b/src/Tests/Broadcast.AspNetCore.TestApp/Controllers/DashboardApiController.cs similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Controllers/DashboardApiController.cs rename to src/Tests/Broadcast.AspNetCore.TestApp/Controllers/DashboardApiController.cs diff --git a/src/Tests/Broadcast.AspNetCore.Test/Controllers/DashboardController.cs b/src/Tests/Broadcast.AspNetCore.TestApp/Controllers/DashboardController.cs similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Controllers/DashboardController.cs rename to src/Tests/Broadcast.AspNetCore.TestApp/Controllers/DashboardController.cs diff --git a/src/Tests/Broadcast.AspNetCore.Test/Controllers/HomeController.cs b/src/Tests/Broadcast.AspNetCore.TestApp/Controllers/HomeController.cs similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Controllers/HomeController.cs rename to src/Tests/Broadcast.AspNetCore.TestApp/Controllers/HomeController.cs diff --git a/src/Tests/Broadcast.AspNetCore.Test/Controllers/StorageController.cs b/src/Tests/Broadcast.AspNetCore.TestApp/Controllers/StorageController.cs similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Controllers/StorageController.cs rename to src/Tests/Broadcast.AspNetCore.TestApp/Controllers/StorageController.cs diff --git a/src/Tests/Broadcast.AspNetCore.Test/Models/DashboardModel.cs b/src/Tests/Broadcast.AspNetCore.TestApp/Models/DashboardModel.cs similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Models/DashboardModel.cs rename to src/Tests/Broadcast.AspNetCore.TestApp/Models/DashboardModel.cs diff --git a/src/Tests/Broadcast.AspNetCore.Test/Models/ErrorViewModel.cs b/src/Tests/Broadcast.AspNetCore.TestApp/Models/ErrorViewModel.cs similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Models/ErrorViewModel.cs rename to src/Tests/Broadcast.AspNetCore.TestApp/Models/ErrorViewModel.cs diff --git a/src/Tests/Broadcast.AspNetCore.Test/Program.cs b/src/Tests/Broadcast.AspNetCore.TestApp/Program.cs similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Program.cs rename to src/Tests/Broadcast.AspNetCore.TestApp/Program.cs diff --git a/src/Tests/Broadcast.AspNetCore.Test/Properties/launchSettings.json b/src/Tests/Broadcast.AspNetCore.TestApp/Properties/launchSettings.json similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Properties/launchSettings.json rename to src/Tests/Broadcast.AspNetCore.TestApp/Properties/launchSettings.json diff --git a/src/Tests/Broadcast.AspNetCore.Test/Startup.cs b/src/Tests/Broadcast.AspNetCore.TestApp/Startup.cs similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Startup.cs rename to src/Tests/Broadcast.AspNetCore.TestApp/Startup.cs diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/Dashboard/EnqueuedTasks.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/EnqueuedTasks.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/Dashboard/EnqueuedTasks.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/EnqueuedTasks.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/Dashboard/FailedTasks.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/FailedTasks.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/Dashboard/FailedTasks.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/FailedTasks.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/Dashboard/Index.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/Index.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/Dashboard/Index.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/Index.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/Dashboard/ProcessedTasks.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/ProcessedTasks.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/Dashboard/ProcessedTasks.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/ProcessedTasks.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/Dashboard/RecurringTasks.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/RecurringTasks.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/Dashboard/RecurringTasks.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/RecurringTasks.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/Dashboard/Servers.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/Servers.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/Dashboard/Servers.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/Servers.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/Dashboard/_Layout.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/_Layout.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/Dashboard/_Layout.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/_Layout.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/Home/Index.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Home/Index.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/Home/Index.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/Home/Index.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/Shared/Error.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/Error.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/Shared/Error.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/Error.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/Shared/_Layout.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/_Layout.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/Shared/_Layout.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/_Layout.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/Shared/_LayoutBasic.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/_LayoutBasic.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/Shared/_LayoutBasic.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/_LayoutBasic.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/Shared/_ValidationScriptsPartial.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/_ValidationScriptsPartial.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/Shared/_ValidationScriptsPartial.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/_ValidationScriptsPartial.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/Storage/Index.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Storage/Index.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/Storage/Index.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/Storage/Index.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/Storage/Partials/_StorageKey.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Storage/Partials/_StorageKey.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/Storage/Partials/_StorageKey.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/Storage/Partials/_StorageKey.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/_ViewImports.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/_ViewImports.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/_ViewImports.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/_ViewImports.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/Views/_ViewStart.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/_ViewStart.cshtml similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/Views/_ViewStart.cshtml rename to src/Tests/Broadcast.AspNetCore.TestApp/Views/_ViewStart.cshtml diff --git a/src/Tests/Broadcast.AspNetCore.Test/appsettings.Development.json b/src/Tests/Broadcast.AspNetCore.TestApp/appsettings.Development.json similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/appsettings.Development.json rename to src/Tests/Broadcast.AspNetCore.TestApp/appsettings.Development.json diff --git a/src/Tests/Broadcast.AspNetCore.Test/appsettings.json b/src/Tests/Broadcast.AspNetCore.TestApp/appsettings.json similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/appsettings.json rename to src/Tests/Broadcast.AspNetCore.TestApp/appsettings.json diff --git a/src/Tests/Broadcast.AspNetCore.Test/compilerconfig.json b/src/Tests/Broadcast.AspNetCore.TestApp/compilerconfig.json similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/compilerconfig.json rename to src/Tests/Broadcast.AspNetCore.TestApp/compilerconfig.json diff --git a/src/Tests/Broadcast.AspNetCore.Test/compilerconfig.json.defaults b/src/Tests/Broadcast.AspNetCore.TestApp/compilerconfig.json.defaults similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/compilerconfig.json.defaults rename to src/Tests/Broadcast.AspNetCore.TestApp/compilerconfig.json.defaults diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/Dashboard.css b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/Dashboard.css similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/Dashboard.css rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/Dashboard.css diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/Dashboard.min.css b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/Dashboard.min.css similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/Dashboard.min.css rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/Dashboard.min.css diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/Dashboard.scss b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/Dashboard.scss similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/Dashboard.scss rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/Dashboard.scss diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/Storage.css b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/Storage.css similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/Storage.css rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/Storage.css diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/Storage.min.css b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/Storage.min.css similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/Storage.min.css rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/Storage.min.css diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/Storage.scss b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/Storage.scss similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/Storage.scss rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/Storage.scss diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/bootstrap.min.css b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/bootstrap.min.css similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/bootstrap.min.css rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/bootstrap.min.css diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/site.css b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/site.css similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/site.css rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/site.css diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/site.min.css b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/site.min.css similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/site.min.css rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/site.min.css diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/site.scss b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/site.scss similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/css/site.scss rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/css/site.scss diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/favicon.ico b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/favicon.ico similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/favicon.ico rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/favicon.ico diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/js/broadcast-base.js b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-base.js similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/js/broadcast-base.js rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-base.js diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/js/broadcast-dashboard.js b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-dashboard.js similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/js/broadcast-dashboard.js rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-dashboard.js diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/js/broadcast-storage.js b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-storage.js similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/js/broadcast-storage.js rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-storage.js diff --git a/src/Tests/Broadcast.AspNetCore.Test/wwwroot/js/site.js b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/site.js similarity index 100% rename from src/Tests/Broadcast.AspNetCore.Test/wwwroot/js/site.js rename to src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/site.js diff --git a/src/Tests/Broadcast.Console.Test/Broadcast.Console.Test.csproj b/src/Tests/Broadcast.Console.TestApp/Broadcast.Console.TestApp.csproj similarity index 100% rename from src/Tests/Broadcast.Console.Test/Broadcast.Console.Test.csproj rename to src/Tests/Broadcast.Console.TestApp/Broadcast.Console.TestApp.csproj diff --git a/src/Tests/Broadcast.Console.Test/Program.cs b/src/Tests/Broadcast.Console.TestApp/Program.cs similarity index 100% rename from src/Tests/Broadcast.Console.Test/Program.cs rename to src/Tests/Broadcast.Console.TestApp/Program.cs From b747ef8c08a4b654364f731eb9b3b9d2b07eca4b Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 4 Nov 2021 21:43:36 +0100 Subject: [PATCH 40/92] Set created store as default store in AspNetCore Setup --- .../BroadcastServiceCollectionExtensions.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Broadcast.Dashboard/BroadcastServiceCollectionExtensions.cs b/src/Broadcast.Dashboard/BroadcastServiceCollectionExtensions.cs index f4ac891..6bd3e66 100644 --- a/src/Broadcast.Dashboard/BroadcastServiceCollectionExtensions.cs +++ b/src/Broadcast.Dashboard/BroadcastServiceCollectionExtensions.cs @@ -16,7 +16,10 @@ namespace Broadcast public static class BroadcastServiceCollectionExtensions { /// - /// Add with a default for managing tasks + /// Configure and initialialize with a default for managing tasks. + /// All items are added to the . + /// The configured ist set as the default . + /// The server has to be added with app.UseBroadcastServer() /// /// /// @@ -26,7 +29,10 @@ public static IServiceCollection AddBroadcast(this IServiceCollection services) } /// - /// Add to the services + /// Configure and initialialize with the passed setup. + /// All items are added to the + /// The configured ist set as the default . + /// The server has to be added with app.UseBroadcastServer() /// /// /// @@ -41,10 +47,12 @@ public static IServiceCollection AddBroadcast(this IServiceCollection services, services.TryAddSingletonChecked(_ => options); var storage = serverSetup.Resolve() ?? new InmemoryStorage(); - + var store = serverSetup.Resolve() ?? new TaskStore(options, storage); services.TryAddSingletonChecked(_ => store); + TaskStore.Setup(() => store); + return services; } From e7e2393b1c7ea339571c7cc06804597436203573 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sat, 6 Nov 2021 12:33:48 +0100 Subject: [PATCH 41/92] BDD Tests for server setup order --- .../Behaviour/SetupOrderTests.cs | 85 +++++++++++++++++++ .../Broadcast.Integration.Test.csproj | 2 + 2 files changed, 87 insertions(+) create mode 100644 src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs new file mode 100644 index 0000000..87d8f6b --- /dev/null +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using BDTest.Attributes; +using BDTest.Test; +using Broadcast.EventSourcing; +using Broadcast.Storage; +using FluentAssertions; +using NUnit.Framework; + +namespace Broadcast.Integration.Test.Behaviour +{ + [SingleThreaded] + [Category("Integration")] + [Story(AsA = "Developer", IWant = "To start a server and add tasks", SoThat = "all tasks are processed independently of the Broadcaster starting order.")] + public class SetupOrderTests : BDTestBase + { + [Test] + [ScenarioText("Start a server after the tasks are added to the storage")] + public void AddServerAfterTask() + { + WithContext(context => + Given(() => CreateStore(context)) + .And(() => StartTasks(context).Wait()) + .When(() => StartServer(context).Wait()) + .Then(() => AllTasksAreProcessed(context)) + .BDTest() + ); + } + + [Test] + [ScenarioText("Start the server before adding the tasks")] + public void ServerThenAddTasks() + { + WithContext(context => + Given(() => CreateStore(context)) + .And(() => StartServer(context).Wait()) + .When(() => StartTasks(context).Wait()) + .Then(() => AllTasksAreProcessed(context)) + .BDTest() + ); + } + + public void CreateStore(BdContext context) + { + context.Store = new TaskStore(new InmemoryStorage()); + BackgroundTask.Setup(() => new BroadcastingClient(context.Store)); + } + + private BdContext StartTasks(BdContext context) + { + for (var i = 0; i < 10; i++) + { + BackgroundTask.Send(() => System.Diagnostics.Debug.WriteLine($"Executed task {i + 1}")); + } + + return context; + } + + public BdContext StartServer(BdContext context) + { + context.Server = new Broadcaster(context.Store); + + return context; + } + + public void AllTasksAreProcessed(BdContext context) + { + context.Store.All(t => t.State == TaskState.Processed).Should().BeTrue(); + } + + public class BdContext + { + public ITaskStore Store { get; set; } + + public Broadcaster Server { get; set; } + + public void Wait() + { + System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(5)).Wait(); + } + } + } +} diff --git a/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj b/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj index 61762c9..32377a7 100644 --- a/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj +++ b/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj @@ -9,6 +9,8 @@ + + From 06f78e745e4918cad2cc512cb74d25e5f72c9f52 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sat, 6 Nov 2021 13:00:17 +0100 Subject: [PATCH 42/92] Ignore test --- .../Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs index 87d8f6b..0248414 100644 --- a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs @@ -17,6 +17,7 @@ namespace Broadcast.Integration.Test.Behaviour public class SetupOrderTests : BDTestBase { [Test] + [Ignore("Adding server after tasks does not work yet")] [ScenarioText("Start a server after the tasks are added to the storage")] public void AddServerAfterTask() { From c71762116d089bdced726c857b95f0fb0d141f22 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sat, 6 Nov 2021 17:30:23 +0100 Subject: [PATCH 43/92] Move logic from BackgroundTask to BroadcastingClient --- src/Broadcast/BackgroundTask.cs | 45 +---- src/Broadcast/BroadcasterExtensions.cs | 66 ++----- src/Broadcast/BroadcastingClientExtensions.cs | 106 +++++++++++ .../Behaviour/SetupOrderTests.cs | 4 +- .../BroadcastingClientExtensionTests.cs | 172 ++++++++++++++++++ 5 files changed, 304 insertions(+), 89 deletions(-) create mode 100644 src/Broadcast/BroadcastingClientExtensions.cs create mode 100644 src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs diff --git a/src/Broadcast/BackgroundTask.cs b/src/Broadcast/BackgroundTask.cs index c5e3b3e..6ef015a 100644 --- a/src/Broadcast/BackgroundTask.cs +++ b/src/Broadcast/BackgroundTask.cs @@ -52,29 +52,7 @@ public static string Recurring(Expression expression, TimeSpan time) /// The Id of the task. This is not the same as the name of the RecurringTask public static string Recurring(string name, Expression expression, TimeSpan time) { - var task = TaskFactory.CreateTask(expression); - task.Time = time; - task.IsRecurring = true; - - if (!string.IsNullOrEmpty(name)) - { - task.Name = name; - } - - // check if the recurring task is already registered - var existing = Client.Store.Storage(s => s.Get(new Storage.StorageKey($"tasks:recurring:{task.Name}"))); - if (existing != null) - { - // update the existing recurring and the task by setting the id of the old task - // this way all properties get overridden with th enew values - task.Id = existing.ReferenceId; - } - - // add the task to the store - // the store will propagate the task to the registered servers - Client.Enqueue(task); - - return task.Id; + return Client.Recurring(name, expression, time); } /// @@ -85,12 +63,7 @@ public static string Recurring(string name, Expression expression, TimeS /// The Id of the task public static string Schedule(Expression expression, TimeSpan time) { - var task = TaskFactory.CreateTask(expression); - task.Time = time; - - Client.Enqueue(task); - - return task.Id; + return Client.Schedule(expression, time); } /// @@ -100,11 +73,7 @@ public static string Schedule(Expression expression, TimeSpan time) /// The Id of the task public static string Send(Expression expression) { - var task = TaskFactory.CreateTask(expression); - - Client.Enqueue(task); - - return task.Id; + return Client.Send(expression); } /// @@ -114,7 +83,7 @@ public static string Send(Expression expression) /// public static void DeleteTask(string taskId) { - Client.Store.Delete(taskId); + Client.DeleteTask(taskId); } /// @@ -123,11 +92,7 @@ public static void DeleteTask(string taskId) /// The name of the recurring Task public static void DeleteRecurringTask(string name) { - var recurring = Client.Store.Storage(s => s.Get(new Storage.StorageKey($"tasks:recurring:{name}"))); - if (recurring != null) - { - Client.Store.Delete(recurring.ReferenceId); - } + Client.DeleteRecurringTask(name); } } } diff --git a/src/Broadcast/BroadcasterExtensions.cs b/src/Broadcast/BroadcasterExtensions.cs index 8690e71..aaf0e98 100644 --- a/src/Broadcast/BroadcasterExtensions.cs +++ b/src/Broadcast/BroadcasterExtensions.cs @@ -26,6 +26,15 @@ public static void Execute(this IBroadcaster broadcaster, Expression act broadcaster.Store.Add(task); } + /// + /// Gets all Tasks that have been processed + /// + /// + public static IEnumerable GetProcessedTasks(this IBroadcaster broadcaster) + { + return broadcaster.Store.Where(s => s.State == TaskState.Processed); + } + /// /// Send a delegate to the task processor server /// @@ -33,11 +42,8 @@ public static void Execute(this IBroadcaster broadcaster, Expression act /// The Task to process public static string Send(this IBroadcaster broadcaster, Expression action) { - var task = TaskFactory.CreateTask(action); - - broadcaster.Store.Add(task); - - return task.Id; + var client = new BroadcastingClient(broadcaster.Store); + return client.Send(action); } /// @@ -49,12 +55,8 @@ public static string Send(this IBroadcaster broadcaster, Expression acti /// The time to execute the task at public static string Schedule(this IBroadcaster broadcaster, Expression expression, TimeSpan time) { - var task = TaskFactory.CreateTask(expression); - task.Time = time; - - broadcaster.Store.Add(task); - - return task.Id; + var client = new BroadcastingClient(broadcaster.Store); + return client.Schedule(expression, time); } /// @@ -78,36 +80,8 @@ public static void Recurring(this IBroadcaster broadcaster, Expression e /// The interval time to execute the task at public static void Recurring(this IBroadcaster broadcaster, string name, Expression expression, TimeSpan time) { - var task = TaskFactory.CreateTask(expression); - task.Time = time; - task.IsRecurring = true; - - if (!string.IsNullOrEmpty(name)) - { - task.Name = name; - } - - // check if the recurring task is already registered - var existing = broadcaster.Store.Storage(s => s.Get(new Storage.StorageKey($"tasks:recurring:{task.Name}"))); - if (existing != null) - { - // update the existing recurring and the task by setting the id of the old task to the new task - // this way all properties get overridden with the new values - task.Id = existing.ReferenceId; - } - - // add the task to the store - // the store will propagate the task to the registered servers - broadcaster.Store.Add(task); - } - - /// - /// Gets all Tasks that have been processed - /// - /// - public static IEnumerable GetProcessedTasks(this IBroadcaster broadcaster) - { - return broadcaster.Store.Where(s => s.State == TaskState.Processed); + var client = new BroadcastingClient(broadcaster.Store); + client.Recurring(name, expression, time); } /// @@ -118,7 +92,8 @@ public static IEnumerable GetProcessedTasks(this IBroadcaster broadcaster /// public static void DeleteTask(this IBroadcaster broadcaster, string taskId) { - broadcaster.Store.Delete(taskId); + var client = new BroadcastingClient(broadcaster.Store); + client.DeleteTask(taskId); } /// @@ -128,11 +103,8 @@ public static void DeleteTask(this IBroadcaster broadcaster, string taskId) /// The name of the recurring Task public static void DeleteRecurringTask(this IBroadcaster broadcaster, string name) { - var recurring = broadcaster.Store.Storage(s => s.Get(new Storage.StorageKey($"tasks:recurring:{name}"))); - if (recurring != null) - { - broadcaster.Store.Delete(recurring.ReferenceId); - } + var client = new BroadcastingClient(broadcaster.Store); + client.DeleteRecurringTask(name); } } } diff --git a/src/Broadcast/BroadcastingClientExtensions.cs b/src/Broadcast/BroadcastingClientExtensions.cs new file mode 100644 index 0000000..1861f36 --- /dev/null +++ b/src/Broadcast/BroadcastingClientExtensions.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Text; +using Broadcast.Composition; +using Broadcast.EventSourcing; +using Broadcast.Server; + +namespace Broadcast +{ + public static class BroadcastingClientExtensions + { + /// + /// Create or update a recurring task. + /// Recurring Tasks are referenced by the name. + /// + /// + /// Unitque name of the recurring Task + /// + /// + /// The Id of the task. This is not the same as the name of the RecurringTask + public static string Recurring(this IBroadcastingClient client, string name, Expression expression, TimeSpan time) + { + var task = TaskFactory.CreateTask(expression); + task.Time = time; + task.IsRecurring = true; + + if (!string.IsNullOrEmpty(name)) + { + task.Name = name; + } + + // check if the recurring task is already registered + var existing = client.Store.Storage(s => s.Get(new Storage.StorageKey($"tasks:recurring:{task.Name}"))); + if (existing != null) + { + // update the existing recurring and the task by setting the id of the old task + // this way all properties get overridden with th enew values + task.Id = existing.ReferenceId; + } + + // add the task to the store + // the store will propagate the task to the registered servers + client.Enqueue(task); + + return task.Id; + } + + /// + /// Adds a scheduled task + /// + /// + /// + /// + /// The Id of the task + public static string Schedule(this IBroadcastingClient client, Expression expression, TimeSpan time) + { + var task = TaskFactory.CreateTask(expression); + task.Time = time; + + client.Enqueue(task); + + return task.Id; + } + + /// + /// Process a task + /// + /// + /// + /// The Id of the task + public static string Send(this IBroadcastingClient client, Expression expression) + { + var task = TaskFactory.CreateTask(expression); + + client.Enqueue(task); + + return task.Id; + } + + /// + /// Deltete a from the Executionpipeline. + /// If a task is allready in the state of the delete will be ignored. + /// + /// + /// + public static void DeleteTask(this IBroadcastingClient client, string taskId) + { + client.Store.Delete(taskId); + } + + /// + /// Delete a recurring task with the associated task execution + /// + /// + /// The name of the recurring Task + public static void DeleteRecurringTask(this IBroadcastingClient client, string name) + { + var recurring = client.Store.Storage(s => s.Get(new Storage.StorageKey($"tasks:recurring:{name}"))); + if (recurring != null) + { + client.Store.Delete(recurring.ReferenceId); + } + } + } +} diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs index 0248414..3af840b 100644 --- a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs @@ -46,14 +46,14 @@ public void ServerThenAddTasks() public void CreateStore(BdContext context) { context.Store = new TaskStore(new InmemoryStorage()); - BackgroundTask.Setup(() => new BroadcastingClient(context.Store)); } private BdContext StartTasks(BdContext context) { + var client = new BroadcastingClient(context.Store); for (var i = 0; i < 10; i++) { - BackgroundTask.Send(() => System.Diagnostics.Debug.WriteLine($"Executed task {i + 1}")); + client.Send(() => System.Diagnostics.Debug.WriteLine($"Executed task {i + 1}")); } return context; diff --git a/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs b/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs new file mode 100644 index 0000000..7d844c1 --- /dev/null +++ b/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Broadcast.EventSourcing; +using Broadcast.Server; +using Broadcast.Storage; +using Moq; +using NUnit.Framework; +using Polaroider; + +namespace Broadcast.Test +{ + public class BroadcastingClientExtensionTests + { + [Test] + public void BroadcastingClient_Recurring() + { + var client = new Mock(); + client.Setup(exp => exp.Store).Returns(() => new Mock().Object); + + client.Object.Recurring("Id", () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + + client.Verify(exp => exp.Enqueue(It.Is(t => t.Name == "Id" && t.State == TaskState.New && t.Time.Value.Seconds == 5)), Times.Once); + } + + [Test] + public void BroadcastingClient_Recurring_IsRecurring() + { + var client = new Mock(); + client.Setup(exp => exp.Store).Returns(() => new Mock().Object); + + client.Object.Recurring("Id", () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + + client.Verify(exp => exp.Enqueue(It.Is(t => t.IsRecurring)), Times.Once); + } + + [Test] + public void BroadcastingClient_Recurring_NoName() + { + var client = new Mock(); + client.Setup(exp => exp.Store).Returns(() => new Mock().Object); + + client.Object.Recurring(null, () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + + client.Verify(exp => exp.Enqueue(It.Is(t => t.IsRecurring && t.Name == "Debug.WriteLine")), Times.Once); + } + + [Test] + public void BroadcastingClient_Recurring_ReturnedId() + { + var client = new Mock(); + client.Setup(exp => exp.Store).Returns(() => new Mock().Object); + + var id = client.Object.Recurring(null, () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + + client.Verify(exp => exp.Enqueue(It.Is(t => t.Id == id)), Times.Once); + } + + [Test] + public void BroadcastingClient_Recurring_OverwriteExistingTask() + { + var existing = new RecurringTask {ReferenceId = "existing"}; + var store = new Mock(); + store.Setup(x => x.Storage(It.IsAny>())).Returns(() => existing); + var client = new Mock(); + client.Setup(exp => exp.Store).Returns(() => store.Object); + + var id = client.Object.Recurring(null, () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + + client.Verify(exp => exp.Enqueue(It.Is(t => t.Id == id && t.Id == existing.ReferenceId)), Times.Once); + } + + [Test] + public void BroadcastingClient_Schedule_Id() + { + var client = new Mock(); + + var id = client.Object.Schedule(() => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + + client.Verify(exp => exp.Enqueue(It.Is(t => t.Id == id)), Times.Once); + } + + [Test] + public void BroadcastingClient_Schedule_Time() + { + var client = new Mock(); + + client.Object.Schedule(() => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + + client.Verify(exp => exp.Enqueue(It.Is(t => t.Time.Value.Seconds == 5)), Times.Once); + } + + [Test] + public void BroadcastingClient_Schedule_NotRecurring() + { + var client = new Mock(); + + client.Object.Schedule(() => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + + client.Verify(exp => exp.Enqueue(It.Is(t => !t.IsRecurring)), Times.Once); + } + + [Test] + public void BroadcastingClient_Send_Id() + { + var client = new Mock(); + + var id = client.Object.Send(() => System.Diagnostics.Debug.WriteLine("Test")); + + client.Verify(exp => exp.Enqueue(It.Is(t => t.Id == id)), Times.Once); + } + + [Test] + public void BroadcastingClient_Send_NoTime() + { + var client = new Mock(); + + client.Object.Send(() => System.Diagnostics.Debug.WriteLine("Test")); + + client.Verify(exp => exp.Enqueue(It.Is(t => t.Time == null)), Times.Once); + } + + [Test] + public void BroadcastingClient_Send_NotRecurring() + { + var client = new Mock(); + + client.Object.Send(() => System.Diagnostics.Debug.WriteLine("Test")); + + client.Verify(exp => exp.Enqueue(It.Is(t => !t.IsRecurring)), Times.Once); + } + + [Test] + public void BroadcastingClient_DeleteTask() + { + var store = new Mock(); + var client = new Mock(); + client.Setup(exp => exp.Store).Returns(() => store.Object); + + client.Object.DeleteTask("id"); + + store.Verify(exp => exp.Delete("id"), Times.Once); + } + + [Test] + public void BroadcastingClient_DeleteRecurringTask_NoExisting() + { + var store = new Mock(); + var client = new Mock(); + client.Setup(exp => exp.Store).Returns(() => store.Object); + + client.Object.DeleteRecurringTask("id"); + + store.Verify(exp => exp.Delete(It.IsAny()), Times.Never); + } + + [Test] + public void BroadcastingClient_DeleteRecurringTask() + { + var existing = new RecurringTask { ReferenceId = "existing" }; + var store = new Mock(); + store.Setup(x => x.Storage(It.IsAny>())).Returns(() => existing); + + var client = new Mock(); + client.Setup(exp => exp.Store).Returns(() => store.Object); + + client.Object.DeleteRecurringTask("id"); + + store.Verify(exp => exp.Delete(existing.ReferenceId), Times.Once); + } + } +} From b5df1c1c05f783fd29a7f58020cfd0c54d07894e Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sat, 6 Nov 2021 17:44:02 +0100 Subject: [PATCH 44/92] Refactored test to run on CI --- .../BroadcastingClientExtensionTests.cs | 96 ++++++++++--------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs b/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs index 7d844c1..551605b 100644 --- a/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs +++ b/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs @@ -15,45 +15,45 @@ public class BroadcastingClientExtensionTests [Test] public void BroadcastingClient_Recurring() { - var client = new Mock(); - client.Setup(exp => exp.Store).Returns(() => new Mock().Object); + var store = new Mock(); + var client = new BroadcastingClient(store.Object); - client.Object.Recurring("Id", () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + client.Recurring("Id", () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); - client.Verify(exp => exp.Enqueue(It.Is(t => t.Name == "Id" && t.State == TaskState.New && t.Time.Value.Seconds == 5)), Times.Once); + store.Verify(exp => exp.Add(It.Is(t => t.Name == "Id" && t.State == TaskState.New && t.Time.Value.Seconds == 5)), Times.Once); } [Test] public void BroadcastingClient_Recurring_IsRecurring() { - var client = new Mock(); - client.Setup(exp => exp.Store).Returns(() => new Mock().Object); + var store = new Mock(); + var client = new BroadcastingClient(store.Object); - client.Object.Recurring("Id", () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + client.Recurring("Id", () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); - client.Verify(exp => exp.Enqueue(It.Is(t => t.IsRecurring)), Times.Once); + store.Verify(exp => exp.Add(It.Is(t => t.IsRecurring)), Times.Once); } [Test] public void BroadcastingClient_Recurring_NoName() { - var client = new Mock(); - client.Setup(exp => exp.Store).Returns(() => new Mock().Object); + var store = new Mock(); + var client = new BroadcastingClient(store.Object); - client.Object.Recurring(null, () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + client.Recurring(null, () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); - client.Verify(exp => exp.Enqueue(It.Is(t => t.IsRecurring && t.Name == "Debug.WriteLine")), Times.Once); + store.Verify(exp => exp.Add(It.Is(t => t.IsRecurring && t.Name == "Debug.WriteLine")), Times.Once); } [Test] public void BroadcastingClient_Recurring_ReturnedId() { - var client = new Mock(); - client.Setup(exp => exp.Store).Returns(() => new Mock().Object); + var store = new Mock(); + var client = new BroadcastingClient(store.Object); - var id = client.Object.Recurring(null, () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + var id = client.Recurring(null, () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); - client.Verify(exp => exp.Enqueue(It.Is(t => t.Id == id)), Times.Once); + store.Verify(exp => exp.Add(It.Is(t => t.Id == id)), Times.Once); } [Test] @@ -62,82 +62,86 @@ public void BroadcastingClient_Recurring_OverwriteExistingTask() var existing = new RecurringTask {ReferenceId = "existing"}; var store = new Mock(); store.Setup(x => x.Storage(It.IsAny>())).Returns(() => existing); - var client = new Mock(); - client.Setup(exp => exp.Store).Returns(() => store.Object); + var client = new BroadcastingClient(store.Object); - var id = client.Object.Recurring(null, () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + var id = client.Recurring(null, () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); - client.Verify(exp => exp.Enqueue(It.Is(t => t.Id == id && t.Id == existing.ReferenceId)), Times.Once); + store.Verify(exp => exp.Add(It.Is(t => t.Id == id && t.Id == existing.ReferenceId)), Times.Once); } [Test] public void BroadcastingClient_Schedule_Id() { - var client = new Mock(); + var store = new Mock(); + var client = new BroadcastingClient(store.Object); - var id = client.Object.Schedule(() => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + var id = client.Schedule(() => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); - client.Verify(exp => exp.Enqueue(It.Is(t => t.Id == id)), Times.Once); + store.Verify(exp => exp.Add(It.Is(t => t.Id == id)), Times.Once); } [Test] public void BroadcastingClient_Schedule_Time() { - var client = new Mock(); + var store = new Mock(); + var client = new BroadcastingClient(store.Object); - client.Object.Schedule(() => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + client.Schedule(() => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); - client.Verify(exp => exp.Enqueue(It.Is(t => t.Time.Value.Seconds == 5)), Times.Once); + store.Verify(exp => exp.Add(It.Is(t => t.Time.Value.Seconds == 5)), Times.Once); } [Test] public void BroadcastingClient_Schedule_NotRecurring() { - var client = new Mock(); + var store = new Mock(); + var client = new BroadcastingClient(store.Object); - client.Object.Schedule(() => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + client.Schedule(() => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); - client.Verify(exp => exp.Enqueue(It.Is(t => !t.IsRecurring)), Times.Once); + store.Verify(exp => exp.Add(It.Is(t => !t.IsRecurring)), Times.Once); } [Test] public void BroadcastingClient_Send_Id() { - var client = new Mock(); + var store = new Mock(); + var client = new BroadcastingClient(store.Object); - var id = client.Object.Send(() => System.Diagnostics.Debug.WriteLine("Test")); + var id = client.Send(() => System.Diagnostics.Debug.WriteLine("Test")); - client.Verify(exp => exp.Enqueue(It.Is(t => t.Id == id)), Times.Once); + store.Verify(exp => exp.Add(It.Is(t => t.Id == id)), Times.Once); } [Test] public void BroadcastingClient_Send_NoTime() { - var client = new Mock(); + var store = new Mock(); + var client = new BroadcastingClient(store.Object); - client.Object.Send(() => System.Diagnostics.Debug.WriteLine("Test")); + client.Send(() => System.Diagnostics.Debug.WriteLine("Test")); - client.Verify(exp => exp.Enqueue(It.Is(t => t.Time == null)), Times.Once); + store.Verify(exp => exp.Add(It.Is(t => t.Time == null)), Times.Once); } [Test] public void BroadcastingClient_Send_NotRecurring() { - var client = new Mock(); + var store = new Mock(); + var client = new BroadcastingClient(store.Object); - client.Object.Send(() => System.Diagnostics.Debug.WriteLine("Test")); + client.Send(() => System.Diagnostics.Debug.WriteLine("Test")); - client.Verify(exp => exp.Enqueue(It.Is(t => !t.IsRecurring)), Times.Once); + store.Verify(exp => exp.Add(It.Is(t => !t.IsRecurring)), Times.Once); } [Test] public void BroadcastingClient_DeleteTask() { var store = new Mock(); - var client = new Mock(); - client.Setup(exp => exp.Store).Returns(() => store.Object); + var client = new BroadcastingClient(store.Object); - client.Object.DeleteTask("id"); + client.DeleteTask("id"); store.Verify(exp => exp.Delete("id"), Times.Once); } @@ -146,10 +150,9 @@ public void BroadcastingClient_DeleteTask() public void BroadcastingClient_DeleteRecurringTask_NoExisting() { var store = new Mock(); - var client = new Mock(); - client.Setup(exp => exp.Store).Returns(() => store.Object); + var client = new BroadcastingClient(store.Object); - client.Object.DeleteRecurringTask("id"); + client.DeleteRecurringTask("id"); store.Verify(exp => exp.Delete(It.IsAny()), Times.Never); } @@ -161,10 +164,9 @@ public void BroadcastingClient_DeleteRecurringTask() var store = new Mock(); store.Setup(x => x.Storage(It.IsAny>())).Returns(() => existing); - var client = new Mock(); - client.Setup(exp => exp.Store).Returns(() => store.Object); + var client = new BroadcastingClient(store.Object); - client.Object.DeleteRecurringTask("id"); + client.DeleteRecurringTask("id"); store.Verify(exp => exp.Delete(existing.ReferenceId), Times.Once); } From 5d8e42f6d50422694c3d0f5498241a21a4f06a44 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sat, 6 Nov 2021 17:49:32 +0100 Subject: [PATCH 45/92] Remove partial method call from tests --- .../BroadcastingClientExtensionTests.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs b/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs index 551605b..83a7eac 100644 --- a/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs +++ b/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs @@ -18,7 +18,7 @@ public void BroadcastingClient_Recurring() var store = new Mock(); var client = new BroadcastingClient(store.Object); - client.Recurring("Id", () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + client.Recurring("Id", () => System.Diagnostics.Trace.WriteLine("Test"), TimeSpan.FromSeconds(5)); store.Verify(exp => exp.Add(It.Is(t => t.Name == "Id" && t.State == TaskState.New && t.Time.Value.Seconds == 5)), Times.Once); } @@ -29,7 +29,7 @@ public void BroadcastingClient_Recurring_IsRecurring() var store = new Mock(); var client = new BroadcastingClient(store.Object); - client.Recurring("Id", () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + client.Recurring("Id", () => System.Diagnostics.Trace.WriteLine("Test"), TimeSpan.FromSeconds(5)); store.Verify(exp => exp.Add(It.Is(t => t.IsRecurring)), Times.Once); } @@ -40,7 +40,7 @@ public void BroadcastingClient_Recurring_NoName() var store = new Mock(); var client = new BroadcastingClient(store.Object); - client.Recurring(null, () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + client.Recurring(null, () => System.Diagnostics.Trace.WriteLine("Test"), TimeSpan.FromSeconds(5)); store.Verify(exp => exp.Add(It.Is(t => t.IsRecurring && t.Name == "Debug.WriteLine")), Times.Once); } @@ -51,7 +51,7 @@ public void BroadcastingClient_Recurring_ReturnedId() var store = new Mock(); var client = new BroadcastingClient(store.Object); - var id = client.Recurring(null, () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + var id = client.Recurring(null, () => System.Diagnostics.Trace.WriteLine("Test"), TimeSpan.FromSeconds(5)); store.Verify(exp => exp.Add(It.Is(t => t.Id == id)), Times.Once); } @@ -64,7 +64,7 @@ public void BroadcastingClient_Recurring_OverwriteExistingTask() store.Setup(x => x.Storage(It.IsAny>())).Returns(() => existing); var client = new BroadcastingClient(store.Object); - var id = client.Recurring(null, () => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + var id = client.Recurring(null, () => System.Diagnostics.Trace.WriteLine("Test"), TimeSpan.FromSeconds(5)); store.Verify(exp => exp.Add(It.Is(t => t.Id == id && t.Id == existing.ReferenceId)), Times.Once); } @@ -75,7 +75,7 @@ public void BroadcastingClient_Schedule_Id() var store = new Mock(); var client = new BroadcastingClient(store.Object); - var id = client.Schedule(() => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + var id = client.Schedule(() => System.Diagnostics.Trace.WriteLine("Test"), TimeSpan.FromSeconds(5)); store.Verify(exp => exp.Add(It.Is(t => t.Id == id)), Times.Once); } @@ -86,7 +86,7 @@ public void BroadcastingClient_Schedule_Time() var store = new Mock(); var client = new BroadcastingClient(store.Object); - client.Schedule(() => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + client.Schedule(() => System.Diagnostics.Trace.WriteLine("Test"), TimeSpan.FromSeconds(5)); store.Verify(exp => exp.Add(It.Is(t => t.Time.Value.Seconds == 5)), Times.Once); } @@ -97,7 +97,7 @@ public void BroadcastingClient_Schedule_NotRecurring() var store = new Mock(); var client = new BroadcastingClient(store.Object); - client.Schedule(() => System.Diagnostics.Debug.WriteLine("Test"), TimeSpan.FromSeconds(5)); + client.Schedule(() => System.Diagnostics.Trace.WriteLine("Test"), TimeSpan.FromSeconds(5)); store.Verify(exp => exp.Add(It.Is(t => !t.IsRecurring)), Times.Once); } @@ -108,7 +108,7 @@ public void BroadcastingClient_Send_Id() var store = new Mock(); var client = new BroadcastingClient(store.Object); - var id = client.Send(() => System.Diagnostics.Debug.WriteLine("Test")); + var id = client.Send(() => System.Diagnostics.Trace.WriteLine("Test")); store.Verify(exp => exp.Add(It.Is(t => t.Id == id)), Times.Once); } @@ -119,7 +119,7 @@ public void BroadcastingClient_Send_NoTime() var store = new Mock(); var client = new BroadcastingClient(store.Object); - client.Send(() => System.Diagnostics.Debug.WriteLine("Test")); + client.Send(() => System.Diagnostics.Trace.WriteLine("Test")); store.Verify(exp => exp.Add(It.Is(t => t.Time == null)), Times.Once); } @@ -130,7 +130,7 @@ public void BroadcastingClient_Send_NotRecurring() var store = new Mock(); var client = new BroadcastingClient(store.Object); - client.Send(() => System.Diagnostics.Debug.WriteLine("Test")); + client.Send(() => System.Diagnostics.Trace.WriteLine("Test")); store.Verify(exp => exp.Add(It.Is(t => !t.IsRecurring)), Times.Once); } From c26a3290ce1cad31a39ed68034a18e2baee8d3eb Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sat, 6 Nov 2021 17:52:38 +0100 Subject: [PATCH 46/92] Remove partial method call from tests --- .../Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs index 3af840b..0a76779 100644 --- a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs @@ -53,7 +53,7 @@ private BdContext StartTasks(BdContext context) var client = new BroadcastingClient(context.Store); for (var i = 0; i < 10; i++) { - client.Send(() => System.Diagnostics.Debug.WriteLine($"Executed task {i + 1}")); + client.Send(() => System.Diagnostics.Trace.WriteLine($"Executed task {i + 1}")); } return context; From 7c28fb51f525a17523f5c202ec31f06ccc07ddb6 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sat, 6 Nov 2021 18:04:46 +0100 Subject: [PATCH 47/92] Fix test --- src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs b/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs index 83a7eac..51eb38f 100644 --- a/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs +++ b/src/Tests/Broadcast.Test/BroadcastingClientExtensionTests.cs @@ -42,7 +42,7 @@ public void BroadcastingClient_Recurring_NoName() client.Recurring(null, () => System.Diagnostics.Trace.WriteLine("Test"), TimeSpan.FromSeconds(5)); - store.Verify(exp => exp.Add(It.Is(t => t.IsRecurring && t.Name == "Debug.WriteLine")), Times.Once); + store.Verify(exp => exp.Add(It.Is(t => t.IsRecurring && t.Name == "Trace.WriteLine")), Times.Once); } [Test] From 42af579322e53a998f91d5844eb97942fd85b39b Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sun, 7 Nov 2021 08:30:19 +0100 Subject: [PATCH 48/92] Behaviour tests for BackgroundTask Setup --- .../Behaviour/BackgroundTaskSetupTests.cs | 65 +++++++++++++++++++ .../Behaviour/BdContext.cs | 16 +++++ .../Behaviour/SetupOrderTests.cs | 12 ---- 3 files changed, 81 insertions(+), 12 deletions(-) create mode 100644 src/Tests/Broadcast.Integration.Test/Behaviour/BackgroundTaskSetupTests.cs create mode 100644 src/Tests/Broadcast.Integration.Test/Behaviour/BdContext.cs diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/BackgroundTaskSetupTests.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/BackgroundTaskSetupTests.cs new file mode 100644 index 0000000..6bb511b --- /dev/null +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/BackgroundTaskSetupTests.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Text; +using BDTest.Attributes; +using BDTest.Test; +using Broadcast.EventSourcing; +using FluentAssertions; +using NUnit.Framework; + +namespace Broadcast.Integration.Test.Behaviour +{ + [Story(AsA = "Developer", IWant = "I want to change the default BroadcastingClient", SoThat = "the Broadcaster uses another store")] + public class BackgroundTaskSetupTests : BDTestBase + { + [TearDown] + public void Teardown() + { + BackgroundTask.Setup(() => new BroadcastingClient()); + } + + [Test] + [ScenarioText("The BroadcastingClient is set to a new store")] + public void OverwriteTheClient() + { + WithContext(context => + Given(() => BackgroundTaskIsSetToDefault()) + .When(() => BackgroundTaskIsSetup()) + .Then(() => TaskStoreIsNotTheSameAsDefault()) + .BDTest() + ); + } + + [Test] + [ScenarioText("The BroadcastingClient is reset to the default store")] + public void ResetTheClient() + { + WithContext(context => + Given(() => BackgroundTaskIsSetup()) + .When(() => BackgroundTaskIsSetToDefault()) + .Then(() => TaskStoreIsSameAsDefault()) + .BDTest() + ); + } + + private void BackgroundTaskIsSetup() + { + BackgroundTask.Setup(() => new BroadcastingClient(new TaskStore())); + } + + private void TaskStoreIsNotTheSameAsDefault() + { + BackgroundTask.Client.Store.Should().NotBeSameAs(TaskStore.Default); + } + + private void BackgroundTaskIsSetToDefault() + { + BackgroundTask.Setup(() => new BroadcastingClient()); + } + + private void TaskStoreIsSameAsDefault() + { + BackgroundTask.Client.Store.Should().BeSameAs(TaskStore.Default); + } + } +} diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/BdContext.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/BdContext.cs new file mode 100644 index 0000000..6cc0d21 --- /dev/null +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/BdContext.cs @@ -0,0 +1,16 @@ +using System; + +namespace Broadcast.Integration.Test.Behaviour +{ + public class BdContext + { + public ITaskStore Store { get; set; } + + public Broadcaster Server { get; set; } + + public void Wait() + { + System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(5)).Wait(); + } + } +} diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs index 0a76779..9908738 100644 --- a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs @@ -70,17 +70,5 @@ public void AllTasksAreProcessed(BdContext context) { context.Store.All(t => t.State == TaskState.Processed).Should().BeTrue(); } - - public class BdContext - { - public ITaskStore Store { get; set; } - - public Broadcaster Server { get; set; } - - public void Wait() - { - System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(5)).Wait(); - } - } } } From 775201c94923b765a7c008f3742b15115ee05f68 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Mon, 8 Nov 2021 07:36:58 +0100 Subject: [PATCH 49/92] Behaviour tests for scheduled tasks --- .../Behaviour/SetupOrderScheduledTests.cs | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderScheduledTests.cs diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderScheduledTests.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderScheduledTests.cs new file mode 100644 index 0000000..cecf2b7 --- /dev/null +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderScheduledTests.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using BDTest.Attributes; +using BDTest.Test; +using Broadcast.EventSourcing; +using Broadcast.Storage; +using FluentAssertions; +using NUnit.Framework; + +namespace Broadcast.Integration.Test.Behaviour +{ + [SingleThreaded] + [Category("Integration")] + [Story(AsA = "Developer", IWant = "To start a server and schedule tasks", SoThat = "all tasks are processed independently of the Broadcaster starting order.")] + public class SetupOrderScheduledTests : BDTestBase + { + [Test] + [Ignore("Adding server after tasks does not work yet")] + [ScenarioText("Start a server after the tasks are scheduled to the storage")] + public void AddServerAfterTaskSchedule() + { + WithContext(context => + Given(() => CreateStore(context)) + .And(() => ScheduleTasks(context).Wait()) + .When(() => StartServer(context).Wait()) + .Then(() => AllTasksAreProcessed(context)) + .BDTest() + ); + } + + [Test] + [ScenarioText("Start the server before scheduling the tasks")] + public void ServerThenAddTaskSchedule() + { + WithContext(context => + Given(() => CreateStore(context)) + .And(() => StartServer(context).Wait()) + .When(() => ScheduleTasks(context).Wait()) + .Then(() => AllTasksAreProcessed(context)) + .BDTest() + ); + } + + public void CreateStore(BdContext context) + { + context.Store = new TaskStore(new InmemoryStorage()); + } + + private BdContext ScheduleTasks(BdContext context) + { + var client = new BroadcastingClient(context.Store); + for (var i = 0; i < 10; i++) + { + client.Schedule(() => System.Diagnostics.Trace.WriteLine($"Executed task {i + 1}"), TimeSpan.FromSeconds(1)); + } + + return context; + } + + public BdContext StartServer(BdContext context) + { + context.Server = new Broadcaster(context.Store); + + return context; + } + + public void AllTasksAreProcessed(BdContext context) + { + context.Store.All(t => t.State == TaskState.Processed).Should().BeTrue(); + } + } +} From a3a1c8d3b19a23bf964f71de6cdfc02ba2d5c78a Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Mon, 8 Nov 2021 13:50:10 +0100 Subject: [PATCH 50/92] Show full timestamp in storage --- .../Assets/js/broadcast-storage.js | 4 ++++ .../Dispatchers/Models/StorageProperty.cs | 14 +++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Broadcast.Dashboard/Assets/js/broadcast-storage.js b/src/Broadcast.Dashboard/Assets/js/broadcast-storage.js index 679b519..90da4b8 100644 --- a/src/Broadcast.Dashboard/Assets/js/broadcast-storage.js +++ b/src/Broadcast.Dashboard/Assets/js/broadcast-storage.js @@ -102,6 +102,10 @@ ${this.createStorageValues(values)} updateStorageElement(elem, values) { elem.querySelector('.broadcast-storage-content').innerHTML = this.createStorageValues(values); + var state = values.find(i => i.key === 'State'); + if (state) { + elem.setAttribute('data-state', state.value); + } } appendChild(list, child) { diff --git a/src/Broadcast.Dashboard/Dispatchers/Models/StorageProperty.cs b/src/Broadcast.Dashboard/Dispatchers/Models/StorageProperty.cs index e21b1d0..32d820c 100644 --- a/src/Broadcast.Dashboard/Dispatchers/Models/StorageProperty.cs +++ b/src/Broadcast.Dashboard/Dispatchers/Models/StorageProperty.cs @@ -1,4 +1,6 @@  +using System; + namespace Broadcast.Dashboard.Dispatchers.Models { /// @@ -12,7 +14,7 @@ public class StorageProperty /// /// public StorageProperty(string key, object value) - : this(key, value?.ToString()) + : this(key, Convert(value)) { } @@ -45,5 +47,15 @@ public override string ToString() { return $"{Key}: {Value}"; } + + private static string Convert(object value) + { + if (value is DateTime dte) + { + return dte.ToString("o"); + } + + return value?.ToString(); + } } } From f8e4ee33ddc498a5ae0a7ec5a68caef5b5b6e23f Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Mon, 8 Nov 2021 13:50:57 +0100 Subject: [PATCH 51/92] CreatedAt timestamp fo tasks --- src/Broadcast/EventSourcing/Task.cs | 14 +++++++++++++- .../Serialization/BroadcastTaskSerializer.cs | 6 ++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Broadcast/EventSourcing/Task.cs b/src/Broadcast/EventSourcing/Task.cs index 0e00920..7e881d1 100644 --- a/src/Broadcast/EventSourcing/Task.cs +++ b/src/Broadcast/EventSourcing/Task.cs @@ -33,6 +33,11 @@ public interface ITask /// TimeSpan? Time { get; set; } + /// + /// Gets the timestamp of creation of the task + /// + DateTime CreatedAt { get; set; } + /// /// Gets if a task is recurring /// @@ -103,9 +108,11 @@ public BroadcastTask(Type type, MethodInfo method, params object[] args) StateChanges = new Dictionary(); Id = Guid.NewGuid().ToString(); Name = Guid.NewGuid().ToString(); + + CreatedAt = DateTime.Now; } - /// + /// public string Id { get; set; } /// @@ -148,6 +155,11 @@ public TaskState State /// public IReadOnlyList Args { get; set; } + /// + /// Gets the timestamp of creation of the task + /// + public DateTime CreatedAt { get; set; } + /// public override string ToString() { diff --git a/src/Broadcast/Storage/Serialization/BroadcastTaskSerializer.cs b/src/Broadcast/Storage/Serialization/BroadcastTaskSerializer.cs index 1ba7872..86f9d66 100644 --- a/src/Broadcast/Storage/Serialization/BroadcastTaskSerializer.cs +++ b/src/Broadcast/Storage/Serialization/BroadcastTaskSerializer.cs @@ -27,7 +27,8 @@ public IEnumerable Serialize(object obj) new HashValue("State", task.State.ToString()), new HashValue("Type", $"{task.Type.FullName}, {task.Type.Assembly.GetName().Name}"), new HashValue("IsRecurring", task.IsRecurring.ToString()), - new HashValue("Time", task.Time?.ToString()) + new HashValue("Time", task.Time?.ToString()), + new HashValue("CreatedAt", task.CreatedAt.ToString("o")) }; foreach (var state in task.StateChanges) @@ -77,7 +78,8 @@ public object Deserialize(IEnumerable hashEntries) State = TypeConverter.Convert(hashEntries.FirstOrDefault(h => h.Name == "State")?.Value), Type = TypeConverter.Convert(hashEntries.FirstOrDefault(h => h.Name == "Type")?.Value), IsRecurring = TypeConverter.Convert(hashEntries.FirstOrDefault(h => h.Name == "IsRecurring")?.Value), - Time = TypeConverter.Convert(hashEntries.FirstOrDefault(h => h.Name == "Time")?.Value) + Time = TypeConverter.Convert(hashEntries.FirstOrDefault(h => h.Name == "Time")?.Value), + CreatedAt = TypeConverter.Convert(hashEntries.FirstOrDefault(h => h.Name == "CreatedAt").Value) }; foreach (var state in hashEntries.Where(h => h.Name.StartsWith("StateChanges:"))) From 43a2bf76b2a9d90e1d4058c36b0027ea58c3866c Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Mon, 8 Nov 2021 14:17:32 +0100 Subject: [PATCH 52/92] Update tests for CreatedAt value --- src/Broadcast/Storage/Serialization/BroadcastTaskSerializer.cs | 2 +- ...tensionsTests_SerializerExtensions_Deserialize_Task.snapshot | 1 + ...ExtensionsTests_SerializerExtensions_Serialize_Task.snapshot | 1 + ...SerializerTests_BroadcastTaskSerializer_Deserialize.snapshot | 1 + ...skSerializerTests_BroadcastTaskSerializer_Serialize.snapshot | 2 ++ ...ests_SerializerExtensions_Deserialize_BroadcastTask.snapshot | 1 + ...sTests_SerializerExtensions_Serialize_BroadcastTask.snapshot | 2 ++ 7 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Broadcast/Storage/Serialization/BroadcastTaskSerializer.cs b/src/Broadcast/Storage/Serialization/BroadcastTaskSerializer.cs index 86f9d66..bab6422 100644 --- a/src/Broadcast/Storage/Serialization/BroadcastTaskSerializer.cs +++ b/src/Broadcast/Storage/Serialization/BroadcastTaskSerializer.cs @@ -79,7 +79,7 @@ public object Deserialize(IEnumerable hashEntries) Type = TypeConverter.Convert(hashEntries.FirstOrDefault(h => h.Name == "Type")?.Value), IsRecurring = TypeConverter.Convert(hashEntries.FirstOrDefault(h => h.Name == "IsRecurring")?.Value), Time = TypeConverter.Convert(hashEntries.FirstOrDefault(h => h.Name == "Time")?.Value), - CreatedAt = TypeConverter.Convert(hashEntries.FirstOrDefault(h => h.Name == "CreatedAt").Value) + CreatedAt = TypeConverter.Convert(hashEntries.FirstOrDefault(h => h.Name == "CreatedAt")?.Value ?? DateTime.MinValue.ToString()) }; foreach (var state in hashEntries.Where(h => h.Name.StartsWith("StateChanges:"))) diff --git a/src/Tests/Broadcast.Storage.Redis.Test/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Deserialize_Task.snapshot b/src/Tests/Broadcast.Storage.Redis.Test/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Deserialize_Task.snapshot index 9e89b51..56668e1 100644 --- a/src/Tests/Broadcast.Storage.Redis.Test/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Deserialize_Task.snapshot +++ b/src/Tests/Broadcast.Storage.Redis.Test/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Deserialize_Task.snapshot @@ -1,6 +1,7 @@ ---data Args: test +CreatedAt: 0000-00-00T00:00:00.0000 Id: 00000000-0000-0000-0000-000000000000 IsRecurring: False Method: WriteLine(System.String) diff --git a/src/Tests/Broadcast.Storage.Redis.Test/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Serialize_Task.snapshot b/src/Tests/Broadcast.Storage.Redis.Test/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Serialize_Task.snapshot index f5993da..2de43c4 100644 --- a/src/Tests/Broadcast.Storage.Redis.Test/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Serialize_Task.snapshot +++ b/src/Tests/Broadcast.Storage.Redis.Test/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Serialize_Task.snapshot @@ -5,6 +5,7 @@ State: New Type: System.Console, System.Console IsRecurring: False Time: 00:00:20 +CreatedAt: 0000-00-00T00:00:00.0000 StateChanges:New: 0000-00-00T00:00:00.0000 Method: WriteLine ArgsType:0: System.String, System.Private.CoreLib diff --git a/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/BroadcastTaskSerializerTests_BroadcastTaskSerializer_Deserialize.snapshot b/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/BroadcastTaskSerializerTests_BroadcastTaskSerializer_Deserialize.snapshot index b6d6386..e0b5bb9 100644 --- a/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/BroadcastTaskSerializerTests_BroadcastTaskSerializer_Deserialize.snapshot +++ b/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/BroadcastTaskSerializerTests_BroadcastTaskSerializer_Deserialize.snapshot @@ -1,6 +1,7 @@ ---data Args: test +CreatedAt: 0000-00-00T00:00:00.0000 Id: id IsRecurring: False Method: WriteLine(System.String) diff --git a/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/BroadcastTaskSerializerTests_BroadcastTaskSerializer_Serialize.snapshot b/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/BroadcastTaskSerializerTests_BroadcastTaskSerializer_Serialize.snapshot index c479c03..57d616c 100644 --- a/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/BroadcastTaskSerializerTests_BroadcastTaskSerializer_Serialize.snapshot +++ b/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/BroadcastTaskSerializerTests_BroadcastTaskSerializer_Serialize.snapshot @@ -11,6 +11,8 @@ Name: IsRecurring Value: False Name: Time Value: null +Name: CreatedAt +Value: 0000-00-00T00:00:00.0000 Name: StateChanges:New Value: 0000-00-00T00:00:00.0000 Name: Method diff --git a/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Deserialize_BroadcastTask.snapshot b/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Deserialize_BroadcastTask.snapshot index b6d6386..e0b5bb9 100644 --- a/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Deserialize_BroadcastTask.snapshot +++ b/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Deserialize_BroadcastTask.snapshot @@ -1,6 +1,7 @@ ---data Args: test +CreatedAt: 0000-00-00T00:00:00.0000 Id: id IsRecurring: False Method: WriteLine(System.String) diff --git a/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Serialize_BroadcastTask.snapshot b/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Serialize_BroadcastTask.snapshot index c479c03..57d616c 100644 --- a/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Serialize_BroadcastTask.snapshot +++ b/src/Tests/Broadcast.Test/Storage/Serialization/_Snapshots/SerializerExtensionsTests_SerializerExtensions_Serialize_BroadcastTask.snapshot @@ -11,6 +11,8 @@ Name: IsRecurring Value: False Name: Time Value: null +Name: CreatedAt +Value: 0000-00-00T00:00:00.0000 Name: StateChanges:New Value: 0000-00-00T00:00:00.0000 Name: Method From 027cf3de89885c4bcaa81ff1e72792c8833a610c Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Mon, 8 Nov 2021 21:36:41 +0100 Subject: [PATCH 53/92] Refactored integration tests to work correctly --- .../Api/BackgroundTaskApiStorageTests.cs | 109 +++++++++ ...tApiTests.cs => BackgroundTaskApiTests.cs} | 77 ++----- .../Api/TaskServerClientApiTests.cs | 213 ------------------ 3 files changed, 127 insertions(+), 272 deletions(-) create mode 100644 src/Tests/Broadcast.Test/Api/BackgroundTaskApiStorageTests.cs rename src/Tests/Broadcast.Test/Api/{BackgroundTaskClientApiTests.cs => BackgroundTaskApiTests.cs} (71%) delete mode 100644 src/Tests/Broadcast.Test/Api/TaskServerClientApiTests.cs diff --git a/src/Tests/Broadcast.Test/Api/BackgroundTaskApiStorageTests.cs b/src/Tests/Broadcast.Test/Api/BackgroundTaskApiStorageTests.cs new file mode 100644 index 0000000..7aaeace --- /dev/null +++ b/src/Tests/Broadcast.Test/Api/BackgroundTaskApiStorageTests.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Broadcast.EventSourcing; +using Broadcast.Processing; +using Broadcast.Storage; +using Moq; +using NUnit.Framework; + +namespace Broadcast.Test.Api +{ + [SingleThreaded] + public class BackgroundTaskApiStorageTests + { + private Mock _processor; + private Mock _scheduler; + private Mock _store; + + [OneTimeSetUp] + public void OneTimeSetup() + { + _processor = new Mock(); + _scheduler = new Mock(); + _store = new Mock(); + //var store = new TaskStore(); + + BroadcastServer.Setup(s => + s.AddScheduler(_scheduler.Object) + .AddProcessor(_processor.Object) + .AddTaskStore(_store.Object) + ); + + BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); + } + + [OneTimeTearDown] + public void OneTimeTeardown() + { + BackgroundTask.Setup(() => new BroadcastingClient()); + } + + [SetUp] + public void Setup() + { + _processor.Reset(); + _scheduler.Reset(); + _store.Reset(); + } + + [Test] + public void BackgroundTask_Api_Send_StaticTrace_StoreAdd() + { + BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); + + // execute a static method + // serializeable + BackgroundTask.Send(() => Trace.WriteLine("test")); + + _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); + } + + [Test] + public void BackgroundTask_Api_Send_Method_StoreAdd() + { + BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); + + // execute a local method + // serializeable + BackgroundTask.Send(() => TestMethod(1)); + + _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); + } + + [Test] + public void BackgroundTask_Api_Send_GenericMethod_StoreAdd() + { + BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); + + // execute a generic method + // serializeable + BackgroundTask.Send(() => GenericMethod(1)); + + _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); + } + + [Test] + public void BackgroundTask_Api_Recurring_Name() + { + BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); + // execute a local method + // serializeable + BackgroundTask.Recurring("BackgroundTask_Api_Recurring", () => TestMethod(1), TimeSpan.FromSeconds(0.5)); + + Task.Delay(1000).Wait(); + + _store.Verify(exp => exp.Add(It.Is(t => t.Name == "BackgroundTask_Api_Recurring")), Times.Once); + } + + + + public void TestMethod(int i) { } + + public void GenericMethod(T value) { } + } +} diff --git a/src/Tests/Broadcast.Test/Api/BackgroundTaskClientApiTests.cs b/src/Tests/Broadcast.Test/Api/BackgroundTaskApiTests.cs similarity index 71% rename from src/Tests/Broadcast.Test/Api/BackgroundTaskClientApiTests.cs rename to src/Tests/Broadcast.Test/Api/BackgroundTaskApiTests.cs index b75709d..c515ab6 100644 --- a/src/Tests/Broadcast.Test/Api/BackgroundTaskClientApiTests.cs +++ b/src/Tests/Broadcast.Test/Api/BackgroundTaskApiTests.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Broadcast.EventSourcing; using Broadcast.Processing; +using Broadcast.Storage; using Moq; using NUnit.Framework; @@ -17,25 +18,34 @@ public class BackgroundTaskApiTests { private Mock _processor; private Mock _scheduler; - private Mock _store; - [SetUp] - public void Setup() + [OneTimeSetUp] + public void OneTimeSetup() { _processor = new Mock(); _scheduler = new Mock(); - _store = new Mock(); + var store = new TaskStore(); BroadcastServer.Setup(s => s.AddScheduler(_scheduler.Object) .AddProcessor(_processor.Object) + .AddTaskStore(store) ); + + BackgroundTask.Setup(() => new BroadcastingClient(store)); + } + + [OneTimeTearDown] + public void OneTimeTeardown() + { + BackgroundTask.Setup(() => new BroadcastingClient()); } - [TearDown] - public void Teardown() + [SetUp] + public void Setup() { - BackgroundTask.Setup(null); + _processor.Reset(); + _scheduler.Reset(); } [Test] @@ -49,19 +59,7 @@ public void BackgroundTask_Api_Send_StaticTrace_Process() _processor.Verify(exp => exp.Process(It.IsAny()), Times.Once); } - - [Test] - public void BackgroundTask_Api_Send_StaticTrace_StoreAdd() - { - BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); - - // execute a static method - // serializeable - BackgroundTask.Send(() => Trace.WriteLine("test")); - - _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); - } - + [Test] public void BackgroundTask_Api_Send_Method_Process() { @@ -74,18 +72,6 @@ public void BackgroundTask_Api_Send_Method_Process() _processor.Verify(exp => exp.Process(It.IsAny()), Times.Once); } - [Test] - public void BackgroundTask_Api_Send_Method_StoreAdd() - { - BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); - - // execute a local method - // serializeable - BackgroundTask.Send(() => TestMethod(1)); - - _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); - } - [Test] public void BackgroundTask_Api_Send_GenericMethod_Process() { @@ -98,19 +84,6 @@ public void BackgroundTask_Api_Send_GenericMethod_Process() _processor.Verify(exp => exp.Process(It.IsAny()), Times.Once); } - [Test] - public void BackgroundTask_Api_Send_GenericMethod_StoreAdd() - { - BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); - - // execute a generic method - // serializeable - BackgroundTask.Send(() => GenericMethod(1)); - - _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); - } - - [Test] public void BackgroundTask_Api_Schedule_StaticTrace() { @@ -180,20 +153,6 @@ public void BackgroundTask_Api_Recurring_GenericMethod() _scheduler.Verify(exp => exp.Enqueue(It.IsAny(), It.IsAny>(), It.IsAny()), Times.Once); } - [Test] - public void BackgroundTask_Api_Recurring_Name() - { - BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); - // execute a local method - // serializeable - BackgroundTask.Recurring("BackgroundTask_Api_Recurring", () => TestMethod(1), TimeSpan.FromSeconds(0.5)); - - Task.Delay(1000).Wait(); - - _store.Verify(exp => exp.Add(It.Is(t => t.Name == "BackgroundTask_Api_Recurring")), Times.Once); - } - - public void TestMethod(int i) { } diff --git a/src/Tests/Broadcast.Test/Api/TaskServerClientApiTests.cs b/src/Tests/Broadcast.Test/Api/TaskServerClientApiTests.cs deleted file mode 100644 index 1cb1286..0000000 --- a/src/Tests/Broadcast.Test/Api/TaskServerClientApiTests.cs +++ /dev/null @@ -1,213 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Broadcast.EventSourcing; -using Broadcast.Processing; -using Moq; -using NUnit.Framework; - -namespace Broadcast.Test.Api -{ - [SingleThreaded] - public class TaskServerClientApiTests - { - private Mock _processor; - private Mock _scheduler; - private Mock _store; - - [SetUp] - public void Setup() - { - _processor = new Mock(); - _scheduler = new Mock(); - _store = new Mock(); - - BroadcastServer.Setup(s => - { - s.AddScheduler(_scheduler.Object); - s.AddProcessor(_processor.Object); - }); - } - - [TearDown] - public void Teardown() - { - BackgroundTask.Setup(null); - } - - [Test] - public void TaskServerClient_Api_Send_StaticTrace_Process() - { - // execute a static method - // serializeable - BackgroundTask.Send(() => Trace.WriteLine("test")); - - BackgroundTask.Client.Store.WaitAll(); - - _processor.Verify(exp => exp.Process(It.IsAny()), Times.Once); - } - - [Test] - public void TaskServerClient_Api_Send_StaticTrace_StoreAdd() - { - BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); - - // execute a static method - // serializeable - BackgroundTask.Send(() => Trace.WriteLine("test")); - - _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); - } - - [Test] - public void TaskServerClient_Api_Send_Method_Process() - { - // execute a local method - // serializeable - BackgroundTask.Send(() => TestMethod(1)); - - BackgroundTask.Client.Store.WaitAll(); - - _processor.Verify(exp => exp.Process(It.IsAny()), Times.Once); - } - - [Test] - public void TaskServerClient_Api_Send_Method_StoreAdd() - { - BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); - - // execute a local method - // serializeable - BackgroundTask.Send(() => TestMethod(1)); - - _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); - } - - [Test] - public void TaskServerClient_Api_Send_GenericMethod_Process() - { - // execute a generic method - // serializeable - BackgroundTask.Send(() => GenericMethod(1)); - - BackgroundTask.Client.Store.WaitAll(); - - _processor.Verify(exp => exp.Process(It.IsAny()), Times.Once); - } - - [Test] - public void TaskServerClient_Api_Send_GenericMethod_StoreAdd() - { - BackgroundTask.Setup(() => new BroadcastingClient(_store.Object)); - - // execute a generic method - // serializeable - BackgroundTask.Send(() => GenericMethod(1)); - - _store.Verify(exp => exp.Add(It.IsAny()), Times.Once); - } - - - - - - - - - - [Test] - public void TaskServerClient_Api_Schedule_StaticTrace() - { - // execute a static method - // serializeable - BackgroundTask.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(1)); - - _scheduler.Verify(exp => exp.Enqueue(It.IsAny(), It.IsAny>(), It.IsAny()), Times.Once); - } - - [Test] - public void TaskServerClient_Api_Schedule_Method() - { - // execute a local method - // serializeable - BackgroundTask.Schedule(() => TestMethod(1), TimeSpan.FromSeconds(1)); - - _scheduler.Verify(exp => exp.Enqueue(It.IsAny(), It.IsAny>(), It.IsAny()), Times.Once); - } - - [Test] - public void TaskServerClient_Api_Schedule_GenericMethod() - { - // execute a generic method - // serializeable - BackgroundTask.Schedule(() => GenericMethod(1), TimeSpan.FromSeconds(1)); - - _scheduler.Verify(exp => exp.Enqueue(It.IsAny(), It.IsAny>(), It.IsAny()), Times.Once); - } - - - - [Test] - public void TaskServerClient_Api_Recurring_StaticTrace() - { - TaskStore.Default.Clear(); - BroadcastServer.Setup(s => { }); - - // execute a static method - // serializeable - BackgroundTask.Recurring(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); - - Task.Delay(2000).Wait(); - - Assert.GreaterOrEqual(BroadcastServer.Server.GetProcessedTasks().Count(), 2); - } - - [Test] - public void TaskServerClient_Api_Recurring_Method() - { - // execute a local method - // serializeable - BackgroundTask.Recurring(() => TestMethod(1), TimeSpan.FromSeconds(0.5)); - - Task.Delay(1000).Wait(); - - _scheduler.Verify(exp => exp.Enqueue(It.IsAny(), It.IsAny>(), It.IsAny()), Times.AtLeastOnce); - } - - [Test] - public void TaskServerClient_Api_Recurring_GenericMethod() - { - // execute a generic method - // serializeable - BackgroundTask.Recurring(() => GenericMethod(1), TimeSpan.FromSeconds(0.5)); - - Task.Delay(1000).Wait(); - - _scheduler.Verify(exp => exp.Enqueue(It.IsAny(), It.IsAny>(), It.IsAny()), Times.AtLeastOnce); - } - - [Test] - public void TaskServerClient_Api_Recurring_Name() - { - TaskStore.Default.Clear(); - BroadcastServer.Setup(s => { }); - - // execute a static method - // serializeable - BackgroundTask.Recurring("TaskServerClient_Api_Recurring", () => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.5)); - - Task.Delay(2000).Wait(); - - Assert.IsTrue(BroadcastServer.Server.GetProcessedTasks().All(t => t.Name == "TaskServerClient_Api_Recurring")); - } - - - public void TestMethod(int i) { } - - public void GenericMethod(T value) { } - } -} From 8c92bc989cc726043226b5f79cef7ccb0550ae1e Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 9 Nov 2021 18:14:31 +0100 Subject: [PATCH 54/92] Check for dead servers is doubled to prevent servers being removed too early --- src/Broadcast/EventSourcing/TaskStore.cs | 4 +++- src/Tests/Broadcast.Test/EventSourcing/TaskStoreTests.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Broadcast/EventSourcing/TaskStore.cs b/src/Broadcast/EventSourcing/TaskStore.cs index fccf7d6..0bf8106 100644 --- a/src/Broadcast/EventSourcing/TaskStore.cs +++ b/src/Broadcast/EventSourcing/TaskStore.cs @@ -256,7 +256,9 @@ public void PropagateServer(ServerModel server) _registeredServers[server.Id] = server; // cleanup dead servers - var expiration = DateTime.Now.Subtract(TimeSpan.FromMilliseconds(_options.HeartbeatInterval)); + // servers are propagated each HeartbeatInterval + // we remove servers that are not propagated at the double time + var expiration = DateTime.Now.Subtract(TimeSpan.FromMilliseconds(_options.HeartbeatInterval * 2)); var deadServers = _registeredServers.Where(item => item.Value.Heartbeat < expiration).Select(item => item.Key).ToList(); foreach (var key in deadServers) { diff --git a/src/Tests/Broadcast.Test/EventSourcing/TaskStoreTests.cs b/src/Tests/Broadcast.Test/EventSourcing/TaskStoreTests.cs index 0212226..44d7447 100644 --- a/src/Tests/Broadcast.Test/EventSourcing/TaskStoreTests.cs +++ b/src/Tests/Broadcast.Test/EventSourcing/TaskStoreTests.cs @@ -458,7 +458,7 @@ public void TaskStore_PropagateServer_Cleanup() { Id = "1", Name = "server", - Heartbeat = DateTime.Now.AddMinutes(-1) + Heartbeat = DateTime.Now.AddMinutes(-2) }; var store = new TaskStore(); From 81af68b997a6b65af7716619aaace1d03ed94cbc Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Wed, 10 Nov 2021 21:18:23 +0100 Subject: [PATCH 55/92] Execute unprocessed tasks when a broadcaster starts --- .../EventSourcing/IStorageObserver.cs | 12 ++ .../EventSourcing/ObserverContext.cs | 32 ++++++ .../EventSourcing/ReschedulingDispatcher.cs | 84 ++++++++++++++ .../EventSourcing/StorageObserver.cs | 40 +++++++ src/Broadcast/EventSourcing/TaskStore.cs | 21 ++-- .../Behaviour/BdContext.cs | 3 + .../Behaviour/SetupMultipleServersTests.cs | 65 +++++++++++ .../Behaviour/SetupOrderScheduledTests.cs | 1 - .../Behaviour/SetupOrderTests.cs | 1 - .../BroadcasterTests.cs | 16 --- .../ReschedulingDispatcherTests.cs | 103 ++++++++++++++++++ .../EventSourcing/StorageObserverTests.cs | 24 ++++ 12 files changed, 374 insertions(+), 28 deletions(-) create mode 100644 src/Broadcast/EventSourcing/IStorageObserver.cs create mode 100644 src/Broadcast/EventSourcing/ObserverContext.cs create mode 100644 src/Broadcast/EventSourcing/ReschedulingDispatcher.cs create mode 100644 src/Broadcast/EventSourcing/StorageObserver.cs create mode 100644 src/Tests/Broadcast.Integration.Test/Behaviour/SetupMultipleServersTests.cs create mode 100644 src/Tests/Broadcast.Test/EventSourcing/ReschedulingDispatcherTests.cs create mode 100644 src/Tests/Broadcast.Test/EventSourcing/StorageObserverTests.cs diff --git a/src/Broadcast/EventSourcing/IStorageObserver.cs b/src/Broadcast/EventSourcing/IStorageObserver.cs new file mode 100644 index 0000000..c192cfe --- /dev/null +++ b/src/Broadcast/EventSourcing/IStorageObserver.cs @@ -0,0 +1,12 @@ +using Broadcast.Server; + +namespace Broadcast.EventSourcing +{ + /// + /// Observer for watching the + /// + public interface IStorageObserver : IBackgroundDispatcher + { + + } +} diff --git a/src/Broadcast/EventSourcing/ObserverContext.cs b/src/Broadcast/EventSourcing/ObserverContext.cs new file mode 100644 index 0000000..3cd9169 --- /dev/null +++ b/src/Broadcast/EventSourcing/ObserverContext.cs @@ -0,0 +1,32 @@ +using Broadcast.Processing; +using Broadcast.Server; + +namespace Broadcast.EventSourcing +{ + /// + /// Context used by the + /// + public class ObserverContext : IServerContext + { + /// + /// Creates a new instance of the context + /// + /// + /// + public ObserverContext(DispatcherLock dispatcherLock, ITaskStore store) + { + DispatcherLock = dispatcherLock; + Store = store; + } + + /// + /// Gets the for the + /// + public DispatcherLock DispatcherLock { get; } + + /// + /// Gets the that the is related to + /// + public ITaskStore Store { get; } + } +} diff --git a/src/Broadcast/EventSourcing/ReschedulingDispatcher.cs b/src/Broadcast/EventSourcing/ReschedulingDispatcher.cs new file mode 100644 index 0000000..e19eee2 --- /dev/null +++ b/src/Broadcast/EventSourcing/ReschedulingDispatcher.cs @@ -0,0 +1,84 @@ +using System; +using Broadcast.Diagnostics; +using Broadcast.Storage; + +namespace Broadcast.EventSourcing +{ + /// + /// + /// + public class ReschedulingDispatcher : IStorageObserver + { + private readonly ILogger _logger; + + /// + /// Creates a new instance of a ReschedulingDispatcher + /// + /// + public ReschedulingDispatcher() + { + _logger = LoggerFactory.Create(); + _logger.Write($"Starting new ReschedulingDispatcher"); + } + + /// + /// Execute the observer + /// + /// + public void Execute(ObserverContext context) + { + if (context.DispatcherLock.IsLocked()) + { + return; + } + + context.DispatcherLock.Lock(); + + try + { + var dispatch = false; + + var dispatched = context.Store.Storage(s => s.GetFetchedTasks()); + foreach (var disp in dispatched) + { + var task = context.Store.Storage(s => s.Get(new StorageKey($"task:{disp}"))); + if (task.State != TaskState.New) + { + // task is already processing + continue; + } + + // delay some time to ensure the task is not yet dispatched + if (task.Time != null && task.CreatedAt + task.Time > DateTime.Now.Subtract(TimeSpan.FromMilliseconds(500))) + { + // task is not scheduled jet + continue; + } + + // move task to enqued list + context.Store.Storage(s => + { + s.RemoveFromList(new StorageKey("tasks:dequeued"), disp); + s.AddToList(new StorageKey("tasks:enqueued"), disp); + }); + + dispatch = true; + + //TODO: check if server is running + //else remove the assigned serverid from the task + } + + if (dispatch) + { + // notify the store to dispatch all tasks again + context.Store.DispatchTasks(); + } + + } + finally + { + context.DispatcherLock.Unlock(); + } + } + } +} diff --git a/src/Broadcast/EventSourcing/StorageObserver.cs b/src/Broadcast/EventSourcing/StorageObserver.cs new file mode 100644 index 0000000..5909a4b --- /dev/null +++ b/src/Broadcast/EventSourcing/StorageObserver.cs @@ -0,0 +1,40 @@ +using Broadcast.Processing; +using Broadcast.Server; +using System; + +namespace Broadcast.EventSourcing +{ + /// + /// Observe the + /// + public class StorageObserver + { + private readonly ITaskStore _store; + private readonly BackgroundServerProcess _process; + private readonly DispatcherLock _dispatcherLock; + + /// + /// Creates a new instance of the StorageObserver + /// + /// + /// + public StorageObserver(ITaskStore store) + { + _store = store ?? throw new ArgumentNullException(nameof(store)); + _dispatcherLock = new DispatcherLock(); + + var context = new ObserverContext(_dispatcherLock, _store); + _process = new BackgroundServerProcess(context); + + } + + /// + /// Start a new + /// + /// + public void Start(IStorageObserver observer) + { + _process.StartNew(observer); + } + } +} diff --git a/src/Broadcast/EventSourcing/TaskStore.cs b/src/Broadcast/EventSourcing/TaskStore.cs index 0bf8106..924ee39 100644 --- a/src/Broadcast/EventSourcing/TaskStore.cs +++ b/src/Broadcast/EventSourcing/TaskStore.cs @@ -27,7 +27,7 @@ public class TaskStore : ITaskStore, IEnumerable private readonly ManualResetEventSlim _event; private readonly BackgroundServerProcess _process; private readonly DispatcherLock _dispatcherLock; - private readonly object _processorLock = new object(); + private readonly StorageObserver _storageObserver; /// /// Gets the default instance of the @@ -88,6 +88,8 @@ public TaskStore(Options options, IStorage storage) ResetEvent = _event }; _process = new BackgroundServerProcess(context); + + _storageObserver = new StorageObserver(this); } /// @@ -174,16 +176,13 @@ public void Delete(string id) public void DispatchTasks() { // check if a thread is allready processing the queue - lock (_processorLock) + if (_dispatcherLock.IsLocked()) { - if (_dispatcherLock.IsLocked()) - { - return; - } - - // start new background thread to process all queued tasks - _process.StartNew(new TaskStoreDispatcher(_dispatcherLock, _storage)); + return; } + + // start new background thread to process all queued tasks + _process.StartNew(new TaskStoreDispatcher(_dispatcherLock, _storage)); } /// @@ -194,8 +193,10 @@ public void DispatchTasks() /// public void RegisterDispatchers(string id, IEnumerable dispatchers) { - _logger.Write($"Register a new set of dispatchers to storage for {id}"); + _logger.Write($"Register a new set of dispatchers to storage for {id}"); _dispatchers.Add(id, dispatchers); + + _storageObserver.Start(new ReschedulingDispatcher()); } /// diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/BdContext.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/BdContext.cs index 6cc0d21..e6356f2 100644 --- a/src/Tests/Broadcast.Integration.Test/Behaviour/BdContext.cs +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/BdContext.cs @@ -1,9 +1,12 @@ using System; +using System.Collections.Generic; namespace Broadcast.Integration.Test.Behaviour { public class BdContext { + public Dictionary Context = new Dictionary(); + public ITaskStore Store { get; set; } public Broadcaster Server { get; set; } diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupMultipleServersTests.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupMultipleServersTests.cs new file mode 100644 index 0000000..e91acda --- /dev/null +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupMultipleServersTests.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Text; +using BDTest.Test; +using Broadcast.EventSourcing; +using Broadcast.Storage; +using FluentAssertions; +using NUnit.Framework; + +namespace Broadcast.Integration.Test.Behaviour +{ + public class SetupMultipleServersTests : BDTestBase + { + [Test] + public void SetupMultipleServers_ExecuteTasksOnce() + { + WithContext(context => + Given(() => CreateStore(context)) + .And(() => ScheduleTasks(context).Wait()) + .When(() => StartMultipleServers(context).Wait()) + .Then(() => TaskIsProcessedOnce()) + .BDTest() + ); + } + + public void CreateStore(BdContext context) + { + context.Store = new TaskStore(new InmemoryStorage()); + } + + private BdContext ScheduleTasks(BdContext context) + { + var client = new BroadcastingClient(context.Store); + client.Send(() => TestTask.Add()); + + return context; + } + + public BdContext StartMultipleServers(BdContext context) + { + context.Context.Add("store1", new Broadcaster(context.Store)); + context.Context.Add("store2", new Broadcaster(context.Store)); + context.Context.Add("store3", new Broadcaster(context.Store)); + context.Context.Add("store4", new Broadcaster(context.Store)); + context.Context.Add("store5", new Broadcaster(context.Store)); + + return context; + } + + public void TaskIsProcessedOnce() + { + TestTask.Count.Should().Be(1); + } + + public class TestTask + { + public static int Count { get; set; } + + public static void Add() + { + Count++; + } + } + } +} diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderScheduledTests.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderScheduledTests.cs index cecf2b7..8f3675f 100644 --- a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderScheduledTests.cs +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderScheduledTests.cs @@ -17,7 +17,6 @@ namespace Broadcast.Integration.Test.Behaviour public class SetupOrderScheduledTests : BDTestBase { [Test] - [Ignore("Adding server after tasks does not work yet")] [ScenarioText("Start a server after the tasks are scheduled to the storage")] public void AddServerAfterTaskSchedule() { diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs index 9908738..294b33f 100644 --- a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupOrderTests.cs @@ -17,7 +17,6 @@ namespace Broadcast.Integration.Test.Behaviour public class SetupOrderTests : BDTestBase { [Test] - [Ignore("Adding server after tasks does not work yet")] [ScenarioText("Start a server after the tasks are added to the storage")] public void AddServerAfterTask() { diff --git a/src/Tests/Broadcast.Integration.Test/BroadcasterTests.cs b/src/Tests/Broadcast.Integration.Test/BroadcasterTests.cs index b49d116..966dc9b 100644 --- a/src/Tests/Broadcast.Integration.Test/BroadcasterTests.cs +++ b/src/Tests/Broadcast.Integration.Test/BroadcasterTests.cs @@ -295,22 +295,6 @@ public void Broadcaster_Scheduler_Simple() Assert.IsTrue(broadcaster.Store.Count(t => t.State == TaskState.Processed) == 3); } - //[Test] - //public void Broadcaster_Scheduler_Delegate() - //{ - // TaskStoreFactory.StoreFactory = () => new TaskStore(); - // var store = TaskStoreFactory.GetStore(); - - // var broadcaster = new Broadcaster(new TaskStore()); - // broadcaster.Schedule(SomeDelegateMethod, TimeSpan.FromSeconds(0.005)); - // broadcaster.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.005)); - // broadcaster.Schedule(() => Trace.WriteLine("test"), TimeSpan.FromSeconds(0.005)); - - // Task.Delay(1000).Wait(); - - // Assert.IsTrue(store.Count(t => t.State == TaskState.Processed) == 3); - //} - private class AsyncReturner { public int GetValue(int index) diff --git a/src/Tests/Broadcast.Test/EventSourcing/ReschedulingDispatcherTests.cs b/src/Tests/Broadcast.Test/EventSourcing/ReschedulingDispatcherTests.cs new file mode 100644 index 0000000..3cedfb4 --- /dev/null +++ b/src/Tests/Broadcast.Test/EventSourcing/ReschedulingDispatcherTests.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Broadcast.EventSourcing; +using Broadcast.Processing; +using Broadcast.Storage; +using Moq; +using NUnit.Framework; + +namespace Broadcast.Test.EventSourcing +{ + public class ReschedulingDispatcherTests + { + [Test] + public void ReschedulingDispatcher_ctor() + { + Assert.DoesNotThrow(() => new ReschedulingDispatcher()); + } + + [Test] + public void ReschedulingDispatcher_Execute() + { + var store = new Mock(); + store.Setup(x => x.Storage>(It.IsAny>>())).Returns(new[] + { + "id1", + "id2" + }); + store.Setup(x => x.Storage(It.IsAny>())).Returns(() => new BroadcastTask { State = TaskState.New }); + + var dispatcherLock = new DispatcherLock(); + var context = new ObserverContext(dispatcherLock, store.Object); + + var dispatcher = new ReschedulingDispatcher(); + dispatcher.Execute(context); + + store.Verify(x => x.DispatchTasks(), Times.Once); + } + + [Test] + public void ReschedulingDispatcher_Execute_TimePassed() + { + var store = new Mock(); + store.Setup(x => x.Storage>(It.IsAny>>())).Returns(new[] + { + "id1" + }); + store.Setup(x => x.Storage(It.IsAny>())).Returns(() => new BroadcastTask + { + State = TaskState.New, + CreatedAt = DateTime.Now.Subtract(TimeSpan.FromMinutes(1)), + Time = TimeSpan.FromSeconds(1) + }); + + var dispatcherLock = new DispatcherLock(); + var context = new ObserverContext(dispatcherLock, store.Object); + + var dispatcher = new ReschedulingDispatcher(); + dispatcher.Execute(context); + + store.Verify(x => x.DispatchTasks(), Times.Once); + } + + [Test] + public void ReschedulingDispatcher_Execute_TimeNotPassed() + { + var store = new Mock(); + store.Setup(x => x.Storage>(It.IsAny>>())).Returns(new[] + { + "id1" + }); + store.Setup(x => x.Storage(It.IsAny>())).Returns(() => new BroadcastTask + { + State = TaskState.New, + CreatedAt = DateTime.Now, + Time = TimeSpan.FromMinutes(1) + }); + + var dispatcherLock = new DispatcherLock(); + var context = new ObserverContext(dispatcherLock, store.Object); + + var dispatcher = new ReschedulingDispatcher(); + dispatcher.Execute(context); + + store.Verify(x => x.DispatchTasks(), Times.Never); + } + + [Test] + public void ReschedulingDispatcher_Execute_Locked() + { + var store = new Mock(); + var dispatcherLock = new DispatcherLock(); + dispatcherLock.Lock(); + + var context = new ObserverContext(dispatcherLock, store.Object); + + var dispatcher = new ReschedulingDispatcher(); + dispatcher.Execute(context); + + store.Verify(x => x.DispatchTasks(), Times.Never); + } + } +} diff --git a/src/Tests/Broadcast.Test/EventSourcing/StorageObserverTests.cs b/src/Tests/Broadcast.Test/EventSourcing/StorageObserverTests.cs new file mode 100644 index 0000000..d2c5db9 --- /dev/null +++ b/src/Tests/Broadcast.Test/EventSourcing/StorageObserverTests.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Broadcast.EventSourcing; +using Moq; +using NUnit.Framework; + +namespace Broadcast.Test.EventSourcing +{ + public class StorageObserverTests + { + [Test] + public void StorageObserver_ctor() + { + Assert.DoesNotThrow(() => new StorageObserver(new Mock().Object)); + } + + [Test] + public void StorageObserver_ctor_NoStore() + { + Assert.Throws(() => new StorageObserver(null)); + } + } +} From 4f9130d01d6e8523150b66fc4e55be2855c717b0 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Wed, 10 Nov 2021 21:57:15 +0100 Subject: [PATCH 56/92] BDD for restarting Server --- .../Behaviour/StopServerInMultisetup.cs | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/Tests/Broadcast.Integration.Test/Behaviour/StopServerInMultisetup.cs diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/StopServerInMultisetup.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/StopServerInMultisetup.cs new file mode 100644 index 0000000..1ba4b12 --- /dev/null +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/StopServerInMultisetup.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using BDTest.Test; +using Broadcast.EventSourcing; +using Broadcast.Storage; +using FluentAssertions; +using NUnit.Framework; + +namespace Broadcast.Integration.Test.Behaviour +{ + public class StopServerInMultisetup : BDTestBase + { + [Test] + public void StopServerInMultisetup_StopServer() + { + WithContext(context => + Given(() => CreateStoreAndServers(context)) + .And(() => ScheduleTasks(context)) + .When(() => StopOneServer(context).Wait()) + .Then(() => HalfTasksAreProcessed(context)) + .BDTest() + ); + } + + [Test] + public void StopServerInMultisetup_RestartServer() + { + WithContext(context => + Given(() => CreateStoreAndServers(context)) + .And(() => ScheduleTasks(context)) + .And(() => StopOneServer(context).Wait()) + .When(() => StartNewServer(context).Wait()) + .Then(() => AllTasksAreProcessed(context)) + .BDTest() + ); + } + + public void CreateStoreAndServers(BdContext context) + { + context.Store = new TaskStore(new InmemoryStorage()); + + context.Context.Add("store1", new Broadcaster(context.Store)); + context.Context.Add("store2", new Broadcaster(context.Store)); + } + + private BdContext ScheduleTasks(BdContext context) + { + var client = new BroadcastingClient(context.Store); + client.Schedule(() => TestTask.Add(), TimeSpan.FromSeconds(1)); + client.Schedule(() => TestTask.Add(), TimeSpan.FromSeconds(1)); + + return context; + } + + public BdContext StopOneServer(BdContext context) + { + ((Broadcaster)context.Context["store2"]).Dispose(); + + return context; + } + + public BdContext StartNewServer(BdContext context) + { + context.Context.Add("store3", new Broadcaster(context.Store)); + return context; + } + + public void HalfTasksAreProcessed(BdContext context) + { + context.Store.Count(t => t.State == TaskState.Processed).Should().Be(1); + context.Store.Count(t => t.State == TaskState.New).Should().Be(1); + } + + public void AllTasksAreProcessed(BdContext context) + { + context.Store.All(t => t.State == TaskState.Processed).Should().BeTrue(); + } + + public class TestTask + { + public static int Count { get; set; } + + public static void Add() + { + Count++; + } + } + } +} From cb6a9458e2d5d2de2839344fde21c95cbf11cd31 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Fri, 19 Nov 2021 22:15:48 +0100 Subject: [PATCH 57/92] Use semaphore to wait on Schduler thread --- src/Broadcast/Scheduling/Scheduler.cs | 2 +- src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Broadcast/Scheduling/Scheduler.cs b/src/Broadcast/Scheduling/Scheduler.cs index dcc7abf..6043820 100644 --- a/src/Broadcast/Scheduling/Scheduler.cs +++ b/src/Broadcast/Scheduling/Scheduler.cs @@ -37,7 +37,7 @@ public Scheduler(IScheduleQueue queue) { _logger = LoggerFactory.Create(); - _scheduleQueue = queue ?? throw new ArgumentNullException(); + _scheduleQueue = queue ?? throw new ArgumentNullException(nameof(queue)); _context = new SchedulerContext { IsRunning = true diff --git a/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs b/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs index 7b74209..3b96ded 100644 --- a/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs +++ b/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs @@ -10,14 +10,17 @@ namespace Broadcast.Scheduling public class SchedulerBackgroundProcess : IBackgroundDispatcher { private readonly IScheduleQueue _queue; + private readonly Semaphore _semaphore; - /// + /// /// Cretes a new instance of the SchedulerTaskDispatcher /// /// public SchedulerBackgroundProcess(IScheduleQueue queue) { _queue = queue ?? throw new ArgumentNullException(nameof(queue)); + + _semaphore = new Semaphore(0, Int32.MaxValue); } /// @@ -42,8 +45,8 @@ public void Execute(ISchedulerContext context) } // Delay the thread to avoid high CPU usage with the infinite loop - System.Threading.Tasks.Task.Delay(50).Wait(); - } + _semaphore.WaitOne(50, true); + } } } } From 477d18592a55b128de7d879237572b0a6ce9b9e7 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sun, 21 Nov 2021 16:08:23 +0100 Subject: [PATCH 58/92] StorageObserver --- src/Broadcast/Configuration/Options.cs | 12 ++- .../EventSourcing/StorageObserver.cs | 83 +++++++++++++++++-- src/Broadcast/EventSourcing/TaskStore.cs | 6 +- .../Scheduling/SchedulerBackgroundProcess.cs | 6 +- .../EventSourcing/StorageObserverTests.cs | 31 ++++++- 5 files changed, 121 insertions(+), 17 deletions(-) diff --git a/src/Broadcast/Configuration/Options.cs b/src/Broadcast/Configuration/Options.cs index e3cd47b..6329e68 100644 --- a/src/Broadcast/Configuration/Options.cs +++ b/src/Broadcast/Configuration/Options.cs @@ -18,5 +18,15 @@ public class Options /// Gets or set the milliseconds that the Hearbeat is propagated to the /// public int HeartbeatInterval { get; set; } = (int)TimeSpan.FromMinutes(1).TotalMilliseconds; - } + + /// + /// Gets or set the milliseconds that the storage cleanup task is run. Defaults to each minute (60000 ms) + /// + public int StorageCleanupInterval { get; set; } = (int)TimeSpan.FromMinutes(1).TotalMilliseconds; + + /// + /// Gets or set the duration that a task is stored after completition or failiure. Defaults to each hour + /// + public int StorageLifetimeDuration { get; set; } = (int)TimeSpan.FromMinutes(60).TotalMilliseconds; + } } diff --git a/src/Broadcast/EventSourcing/StorageObserver.cs b/src/Broadcast/EventSourcing/StorageObserver.cs index 5909a4b..8b57759 100644 --- a/src/Broadcast/EventSourcing/StorageObserver.cs +++ b/src/Broadcast/EventSourcing/StorageObserver.cs @@ -1,31 +1,61 @@ using Broadcast.Processing; using Broadcast.Server; using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Broadcast.Configuration; namespace Broadcast.EventSourcing { /// /// Observe the /// - public class StorageObserver + public class StorageObserver : IDisposable { - private readonly ITaskStore _store; private readonly BackgroundServerProcess _process; - private readonly DispatcherLock _dispatcherLock; + private readonly WaitHandle _waitHandle; /// /// Creates a new instance of the StorageObserver /// /// + /// /// - public StorageObserver(ITaskStore store) + public StorageObserver(ITaskStore store, Options options) { - _store = store ?? throw new ArgumentNullException(nameof(store)); - _dispatcherLock = new DispatcherLock(); + if(store == null) + { + throw new ArgumentNullException(nameof(store)); + } - var context = new ObserverContext(_dispatcherLock, _store); + var context = new ObserverContext(new DispatcherLock(), store); _process = new BackgroundServerProcess(context); - + + _waitHandle = new Semaphore(0, Int32.MaxValue); + StartScheduler(this, options, _waitHandle); + } + + private void StartScheduler(StorageObserver observer, Options options, WaitHandle waitHandle) + { + Task.Factory.StartNew(() => ExecuteScheduler(observer, options, waitHandle), + CancellationToken.None, + TaskCreationOptions.None, + TaskScheduler.Default); + } + + private void ExecuteScheduler(StorageObserver observer, Options options, WaitHandle waitHandle) + { + // loop until the waithandle is disposed + while (!waitHandle.SafeWaitHandle.IsClosed) + { + // start a new dispatcher to cleanup the storage + observer.Start(new StorageCleanupDispatcher(options)); + + // Delay the thread to avoid high CPU usage with the infinite loop + waitHandle.WaitOne(TimeSpan.FromSeconds(options.StorageCleanupInterval), true); + } } /// @@ -36,5 +66,42 @@ public void Start(IStorageObserver observer) { _process.StartNew(observer); } + + /// + /// Dispose the StorageObserver + /// + public void Dispose() + { + _waitHandle.Dispose(); + } + } + + public class StorageCleanupDispatcher : IStorageObserver + { + private readonly Options _options; + + public StorageCleanupDispatcher(Options options) + { + _options = options; + } + + public void Execute(ObserverContext context) + { + var tasks = GetTasks(context.Store).ToList(); + foreach (var task in tasks) + { + context.Store.Storage(s => s.Delete(new Storage.StorageKey($"task:{task.Id}"))); + } + + //TODO: delete servers + } + + private IEnumerable GetTasks(ITaskStore store) + { + return store.Where(t => (t.State == TaskState.Processed || + t.State == TaskState.Faulted || + t.State == TaskState.Deleted) && + t.StateChanges[t.State] < DateTime.Now.Subtract(TimeSpan.FromMilliseconds(_options.StorageLifetimeDuration))); + } } } diff --git a/src/Broadcast/EventSourcing/TaskStore.cs b/src/Broadcast/EventSourcing/TaskStore.cs index 924ee39..dde0b24 100644 --- a/src/Broadcast/EventSourcing/TaskStore.cs +++ b/src/Broadcast/EventSourcing/TaskStore.cs @@ -89,7 +89,7 @@ public TaskStore(Options options, IStorage storage) }; _process = new BackgroundServerProcess(context); - _storageObserver = new StorageObserver(this); + //_storageObserver = new StorageObserver(this, _options); } /// @@ -193,10 +193,10 @@ public void DispatchTasks() /// public void RegisterDispatchers(string id, IEnumerable dispatchers) { - _logger.Write($"Register a new set of dispatchers to storage for {id}"); + _logger.Write($"Register a new set of dispatchers to storage for {id}"); _dispatchers.Add(id, dispatchers); - _storageObserver.Start(new ReschedulingDispatcher()); + //_storageObserver.Start(new ReschedulingDispatcher()); } /// diff --git a/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs b/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs index 3b96ded..c060102 100644 --- a/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs +++ b/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs @@ -10,7 +10,7 @@ namespace Broadcast.Scheduling public class SchedulerBackgroundProcess : IBackgroundDispatcher { private readonly IScheduleQueue _queue; - private readonly Semaphore _semaphore; + private readonly Semaphore _waitHandle; /// /// Cretes a new instance of the SchedulerTaskDispatcher @@ -20,7 +20,7 @@ public SchedulerBackgroundProcess(IScheduleQueue queue) { _queue = queue ?? throw new ArgumentNullException(nameof(queue)); - _semaphore = new Semaphore(0, Int32.MaxValue); + _waitHandle = new Semaphore(0, Int32.MaxValue); } /// @@ -45,7 +45,7 @@ public void Execute(ISchedulerContext context) } // Delay the thread to avoid high CPU usage with the infinite loop - _semaphore.WaitOne(50, true); + _waitHandle.WaitOne(50, true); } } } diff --git a/src/Tests/Broadcast.Test/EventSourcing/StorageObserverTests.cs b/src/Tests/Broadcast.Test/EventSourcing/StorageObserverTests.cs index d2c5db9..90a747e 100644 --- a/src/Tests/Broadcast.Test/EventSourcing/StorageObserverTests.cs +++ b/src/Tests/Broadcast.Test/EventSourcing/StorageObserverTests.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using Broadcast.Configuration; using Broadcast.EventSourcing; using Moq; using NUnit.Framework; @@ -12,13 +14,38 @@ public class StorageObserverTests [Test] public void StorageObserver_ctor() { - Assert.DoesNotThrow(() => new StorageObserver(new Mock().Object)); + Assert.DoesNotThrow(() => new StorageObserver(new Mock().Object, new Options())); } [Test] public void StorageObserver_ctor_NoStore() { - Assert.Throws(() => new StorageObserver(null)); + Assert.Throws(() => new StorageObserver(null, new Options())); + } + + [Test] + public void StorageObserver_StartNew() + { + var store = new Mock(); + store.Setup(x => x.GetEnumerator()).Returns(new List().GetEnumerator()); + var task = new TestObserver(); + + var observer = new StorageObserver(store.Object, new Options()); + observer.Start(task); + + Task.Delay(50).Wait(); + + Assert.IsTrue(task.Executed); + } + + public class TestObserver : IStorageObserver + { + public void Execute(ObserverContext context) + { + Executed = true; + } + + public bool Executed { get; private set; } } } } From 2d409a69addd3357ac71056430d80db63a500a53 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sun, 21 Nov 2021 22:03:38 +0100 Subject: [PATCH 59/92] Start observer in a therad instead of the task --- .../EventSourcing/StorageObserver.cs | 33 ++++++++++++------- src/Broadcast/EventSourcing/TaskStore.cs | 6 ++-- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/Broadcast/EventSourcing/StorageObserver.cs b/src/Broadcast/EventSourcing/StorageObserver.cs index 8b57759..904b610 100644 --- a/src/Broadcast/EventSourcing/StorageObserver.cs +++ b/src/Broadcast/EventSourcing/StorageObserver.cs @@ -15,7 +15,7 @@ namespace Broadcast.EventSourcing public class StorageObserver : IDisposable { private readonly BackgroundServerProcess _process; - private readonly WaitHandle _waitHandle; + private readonly Semaphore _waitHandle; /// /// Creates a new instance of the StorageObserver @@ -33,28 +33,36 @@ public StorageObserver(ITaskStore store, Options options) var context = new ObserverContext(new DispatcherLock(), store); _process = new BackgroundServerProcess(context); - _waitHandle = new Semaphore(0, Int32.MaxValue); - StartScheduler(this, options, _waitHandle); + //_waitHandle = new Semaphore(0, Int32.MaxValue); + StartScheduler(_process, options); } - private void StartScheduler(StorageObserver observer, Options options, WaitHandle waitHandle) + private void StartScheduler(BackgroundServerProcess process, Options options) { - Task.Factory.StartNew(() => ExecuteScheduler(observer, options, waitHandle), - CancellationToken.None, - TaskCreationOptions.None, - TaskScheduler.Default); + //Task.Factory.StartNew(() => ExecuteScheduler(process, options), + // CancellationToken.None, + // TaskCreationOptions.LongRunning| TaskCreationOptions.RunContinuationsAsynchronously, + // TaskScheduler.Default); + var thread = new Thread(() => ExecuteScheduler(process, options)) + { + IsBackground = true, + Name = $"{nameof(StorageObserver)}", + }; + thread.Start(); } - private void ExecuteScheduler(StorageObserver observer, Options options, WaitHandle waitHandle) + private void ExecuteScheduler(BackgroundServerProcess process, Options options) { // loop until the waithandle is disposed - while (!waitHandle.SafeWaitHandle.IsClosed) + //while (!waitHandle.SafeWaitHandle.IsClosed) + while(true) { // start a new dispatcher to cleanup the storage - observer.Start(new StorageCleanupDispatcher(options)); + process.StartNew(new StorageCleanupDispatcher(options)); // Delay the thread to avoid high CPU usage with the infinite loop - waitHandle.WaitOne(TimeSpan.FromSeconds(options.StorageCleanupInterval), true); + //waitHandle.WaitOne(TimeSpan.FromMilliseconds(options.StorageCleanupInterval), true); + Task.Delay(TimeSpan.FromSeconds(60)).Wait(); } } @@ -72,6 +80,7 @@ public void Start(IStorageObserver observer) /// public void Dispose() { + _waitHandle.Release(); _waitHandle.Dispose(); } } diff --git a/src/Broadcast/EventSourcing/TaskStore.cs b/src/Broadcast/EventSourcing/TaskStore.cs index dde0b24..3826c4f 100644 --- a/src/Broadcast/EventSourcing/TaskStore.cs +++ b/src/Broadcast/EventSourcing/TaskStore.cs @@ -89,7 +89,7 @@ public TaskStore(Options options, IStorage storage) }; _process = new BackgroundServerProcess(context); - //_storageObserver = new StorageObserver(this, _options); + _storageObserver = new StorageObserver(this, _options); } /// @@ -196,7 +196,7 @@ public void RegisterDispatchers(string id, IEnumerable dispatchers) _logger.Write($"Register a new set of dispatchers to storage for {id}"); _dispatchers.Add(id, dispatchers); - //_storageObserver.Start(new ReschedulingDispatcher()); + _storageObserver.Start(new ReschedulingDispatcher()); } /// @@ -299,6 +299,8 @@ public bool WaitAll() WaitHandle.WaitOne(50); } + _storageObserver.Dispose(); + // then we wait for all dequeued tasks to be dispatched to all dispatchers // all tasks are passed to the dispatchers in a own thread // so we wait for these to end From 72701c8cba65d77c07ea45bcf722a0b78281bea4 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Mon, 22 Nov 2021 21:56:50 +0100 Subject: [PATCH 60/92] StorageObserver --- .../EventSourcing/StorageObserver.cs | 38 ++++++++++--------- .../Scheduling/SchedulerBackgroundProcess.cs | 4 +- .../Server/BackgroundServerProcess.cs | 6 ++- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/Broadcast/EventSourcing/StorageObserver.cs b/src/Broadcast/EventSourcing/StorageObserver.cs index 904b610..5ee01a9 100644 --- a/src/Broadcast/EventSourcing/StorageObserver.cs +++ b/src/Broadcast/EventSourcing/StorageObserver.cs @@ -15,7 +15,7 @@ namespace Broadcast.EventSourcing public class StorageObserver : IDisposable { private readonly BackgroundServerProcess _process; - private readonly Semaphore _waitHandle; + private readonly WaitHandle _waitHandle; /// /// Creates a new instance of the StorageObserver @@ -33,36 +33,41 @@ public StorageObserver(ITaskStore store, Options options) var context = new ObserverContext(new DispatcherLock(), store); _process = new BackgroundServerProcess(context); - //_waitHandle = new Semaphore(0, Int32.MaxValue); - StartScheduler(_process, options); + _waitHandle = new AutoResetEvent(false); + StartScheduler(_process, options, _waitHandle); } - private void StartScheduler(BackgroundServerProcess process, Options options) + private void StartScheduler(BackgroundServerProcess process, Options options, WaitHandle waitHandle) { - //Task.Factory.StartNew(() => ExecuteScheduler(process, options), - // CancellationToken.None, - // TaskCreationOptions.LongRunning| TaskCreationOptions.RunContinuationsAsynchronously, - // TaskScheduler.Default); - var thread = new Thread(() => ExecuteScheduler(process, options)) + // Task.Factory.StartNew : Starts a new task that will run in a thread pool thread or may run in the same thread. + // If it is ran in a thread pool thread, the thread is returned to the pool when done. + // Thread creation/destruction is an expensive process. + // + // new Thread().Start() : Will always run in a new thread + // + // Here we use a Thread instead of a task. + // This way we can ensure that the thread is a backgroundthread + // Because it is only a cleanup process, it is run with the lowest ThreadPriority + // + var thread = new Thread(() => ExecuteScheduler(process, options, waitHandle)) { IsBackground = true, Name = $"{nameof(StorageObserver)}", + Priority = ThreadPriority.Lowest }; thread.Start(); } - private void ExecuteScheduler(BackgroundServerProcess process, Options options) + private void ExecuteScheduler(BackgroundServerProcess process, Options options, WaitHandle waitHandle) { // loop until the waithandle is disposed - //while (!waitHandle.SafeWaitHandle.IsClosed) - while(true) + while (!waitHandle.SafeWaitHandle.IsClosed) { + // Delay the thread to avoid high CPU usage with the infinite loop + waitHandle.WaitOne(TimeSpan.FromMilliseconds(options.StorageCleanupInterval), true); + // start a new dispatcher to cleanup the storage process.StartNew(new StorageCleanupDispatcher(options)); - - // Delay the thread to avoid high CPU usage with the infinite loop - //waitHandle.WaitOne(TimeSpan.FromMilliseconds(options.StorageCleanupInterval), true); - Task.Delay(TimeSpan.FromSeconds(60)).Wait(); } } @@ -80,7 +85,6 @@ public void Start(IStorageObserver observer) /// public void Dispose() { - _waitHandle.Release(); _waitHandle.Dispose(); } } diff --git a/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs b/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs index c060102..decc008 100644 --- a/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs +++ b/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs @@ -10,7 +10,7 @@ namespace Broadcast.Scheduling public class SchedulerBackgroundProcess : IBackgroundDispatcher { private readonly IScheduleQueue _queue; - private readonly Semaphore _waitHandle; + private readonly AutoResetEvent _waitHandle; /// /// Cretes a new instance of the SchedulerTaskDispatcher @@ -20,7 +20,7 @@ public SchedulerBackgroundProcess(IScheduleQueue queue) { _queue = queue ?? throw new ArgumentNullException(nameof(queue)); - _waitHandle = new Semaphore(0, Int32.MaxValue); + _waitHandle = new AutoResetEvent(false); } /// diff --git a/src/Broadcast/Server/BackgroundServerProcess.cs b/src/Broadcast/Server/BackgroundServerProcess.cs index 4b4503f..ae236f1 100644 --- a/src/Broadcast/Server/BackgroundServerProcess.cs +++ b/src/Broadcast/Server/BackgroundServerProcess.cs @@ -30,7 +30,11 @@ public BackgroundServerProcess(T context) /// public void StartNew(IBackgroundDispatcher dispatcher) { - var thread = Task.Factory.StartNew(() => dispatcher.Execute(_context), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default); + var thread = Task.Factory.StartNew(() => dispatcher.Execute(_context), + CancellationToken.None, + TaskCreationOptions.None, + TaskScheduler.Default); + _threadList.Add(thread); } From e4d0e5598507d7aa404c70061ec7518f70f397d4 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Mon, 22 Nov 2021 22:26:16 +0100 Subject: [PATCH 61/92] Implemented StorageCleanupDispatcher --- .../EventSourcing/StorageCleanupDispatcher.cs | 47 +++++++++++ .../EventSourcing/StorageObserver.cs | 32 -------- .../StorageCleanupDispatcherTests.cs | 81 +++++++++++++++++++ 3 files changed, 128 insertions(+), 32 deletions(-) create mode 100644 src/Broadcast/EventSourcing/StorageCleanupDispatcher.cs create mode 100644 src/Tests/Broadcast.Test/EventSourcing/StorageCleanupDispatcherTests.cs diff --git a/src/Broadcast/EventSourcing/StorageCleanupDispatcher.cs b/src/Broadcast/EventSourcing/StorageCleanupDispatcher.cs new file mode 100644 index 0000000..6509f3f --- /dev/null +++ b/src/Broadcast/EventSourcing/StorageCleanupDispatcher.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Broadcast.Configuration; + +namespace Broadcast.EventSourcing +{ + /// + /// Dispatcher to cleanup the storage from old tasks + /// + public class StorageCleanupDispatcher : IStorageObserver + { + private readonly Options _options; + + /// + /// Creates a new instance of a StorageCleanupDispatcher + /// + /// + public StorageCleanupDispatcher(Options options) + { + _options = options; + } + + /// + /// Execute the dispatcher + /// + /// + public void Execute(ObserverContext context) + { + var tasks = GetTasks(context.Store).ToList(); + foreach (var task in tasks) + { + context.Store.Storage(s => s.Delete(new Storage.StorageKey($"task:{task.Id}"))); + } + + //TODO: delete servers + } + + private IEnumerable GetTasks(ITaskStore store) + { + return store.Where(t => (t.State == TaskState.Processed || + t.State == TaskState.Faulted || + t.State == TaskState.Deleted) && + t.StateChanges[t.State] < DateTime.Now.Subtract(TimeSpan.FromMilliseconds(_options.StorageLifetimeDuration))); + } + } +} diff --git a/src/Broadcast/EventSourcing/StorageObserver.cs b/src/Broadcast/EventSourcing/StorageObserver.cs index 5ee01a9..36d7d8c 100644 --- a/src/Broadcast/EventSourcing/StorageObserver.cs +++ b/src/Broadcast/EventSourcing/StorageObserver.cs @@ -1,10 +1,7 @@ using Broadcast.Processing; using Broadcast.Server; using System; -using System.Collections.Generic; -using System.Linq; using System.Threading; -using System.Threading.Tasks; using Broadcast.Configuration; namespace Broadcast.EventSourcing @@ -88,33 +85,4 @@ public void Dispose() _waitHandle.Dispose(); } } - - public class StorageCleanupDispatcher : IStorageObserver - { - private readonly Options _options; - - public StorageCleanupDispatcher(Options options) - { - _options = options; - } - - public void Execute(ObserverContext context) - { - var tasks = GetTasks(context.Store).ToList(); - foreach (var task in tasks) - { - context.Store.Storage(s => s.Delete(new Storage.StorageKey($"task:{task.Id}"))); - } - - //TODO: delete servers - } - - private IEnumerable GetTasks(ITaskStore store) - { - return store.Where(t => (t.State == TaskState.Processed || - t.State == TaskState.Faulted || - t.State == TaskState.Deleted) && - t.StateChanges[t.State] < DateTime.Now.Subtract(TimeSpan.FromMilliseconds(_options.StorageLifetimeDuration))); - } - } } diff --git a/src/Tests/Broadcast.Test/EventSourcing/StorageCleanupDispatcherTests.cs b/src/Tests/Broadcast.Test/EventSourcing/StorageCleanupDispatcherTests.cs new file mode 100644 index 0000000..341f669 --- /dev/null +++ b/src/Tests/Broadcast.Test/EventSourcing/StorageCleanupDispatcherTests.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Broadcast.Configuration; +using Broadcast.EventSourcing; +using Broadcast.Processing; +using Broadcast.Storage; +using Moq; +using NUnit.Framework; + +namespace Broadcast.Test.EventSourcing +{ + public class StorageCleanupDispatcherTests + { + [Test] + public void StorageCleanupDispatcher_ctor() + { + Assert.DoesNotThrow(() => new StorageCleanupDispatcher(new Options())); + } + + [Test] + public void StorageCleanupDispatcher_Execute() + { + var store = new Mock(); + store.Setup(x => x.GetEnumerator()).Returns(() => new List().GetEnumerator()); + + var dispatcher = new StorageCleanupDispatcher(new Options()); + dispatcher.Execute(new ObserverContext(new DispatcherLock(), store.Object)); + + store.Verify(x => x.GetEnumerator(), Times.Once); + } + + [TestCase(TaskState.Processed)] + [TestCase(TaskState.Faulted)] + [TestCase(TaskState.Deleted)] + public void StorageCleanupDispatcher_Execute_Clean(TaskState state) + { + var task = new BroadcastTask { State = state }; + task.StateChanges[task.State] = DateTime.Now.Subtract(TimeSpan.FromMinutes(10)); + var store = new Mock(); + store.Setup(x => x.GetEnumerator()).Returns(() => new List { task }.GetEnumerator()); + + var dispatcher = new StorageCleanupDispatcher(new Options { StorageLifetimeDuration = 5000 }); + dispatcher.Execute(new ObserverContext(new DispatcherLock(), store.Object)); + + store.Verify(x => x.Storage(It.IsAny>()), Times.Once); + } + + [TestCase(TaskState.New)] + [TestCase(TaskState.Processing)] + [TestCase(TaskState.Dequeued)] + [TestCase(TaskState.Queued)] + public void StorageCleanupDispatcher_Execute_Clean_InvalidState(TaskState state) + { + var task = new BroadcastTask { State = state }; + task.StateChanges[task.State] = DateTime.Now.Subtract(TimeSpan.FromMinutes(10)); + var store = new Mock(); + store.Setup(x => x.GetEnumerator()).Returns(() => new List { task }.GetEnumerator()); + + var dispatcher = new StorageCleanupDispatcher(new Options { StorageLifetimeDuration = 5000 }); + dispatcher.Execute(new ObserverContext(new DispatcherLock(), store.Object)); + + store.Verify(x => x.Storage(It.IsAny>()), Times.Never); + } + + [TestCase(TaskState.Processed)] + [TestCase(TaskState.Faulted)] + [TestCase(TaskState.Deleted)] + public void StorageCleanupDispatcher_Execute_Clean_NotExpired(TaskState state) + { + var task = new BroadcastTask { State = state }; + var store = new Mock(); + store.Setup(x => x.GetEnumerator()).Returns(() => new List { task }.GetEnumerator()); + + var dispatcher = new StorageCleanupDispatcher(new Options { StorageLifetimeDuration = 5000 }); + dispatcher.Execute(new ObserverContext(new DispatcherLock(), store.Object)); + + store.Verify(x => x.Storage(It.IsAny>()), Times.Never); + } + } +} From 5f391d78cb12f75d721563d66c3da91c3a548fe4 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 23 Nov 2021 22:20:05 +0100 Subject: [PATCH 62/92] ThreadWait to handle long running threads --- src/Broadcast/Broadcaster.cs | 5 +- .../EventSourcing/StorageObserver.cs | 18 +++--- src/Broadcast/Scheduling/ISchedulerContext.cs | 4 +- src/Broadcast/Scheduling/Scheduler.cs | 7 +-- .../Scheduling/SchedulerBackgroundProcess.cs | 9 +-- src/Broadcast/Scheduling/SchedulerContext.cs | 12 ++-- src/Broadcast/Server/BroadcasterConterxt.cs | 25 ++++++-- .../Server/BroadcasterHeartbeatDispatcher.cs | 7 +-- src/Broadcast/Server/IBroadcasterConterxt.cs | 9 +-- src/Broadcast/ThreadWait.cs | 60 +++++++++++++++++++ .../SchedulerBackgroundProcessTests.cs | 25 +++----- .../Scheduling/SchedulerContextTests.cs | 11 +++- .../BroadcasterHeartbeatDispatcherTests.cs | 9 +-- src/Tests/Broadcast.Test/ThreadWaitTests.cs | 55 +++++++++++++++++ 14 files changed, 190 insertions(+), 66 deletions(-) create mode 100644 src/Broadcast/ThreadWait.cs create mode 100644 src/Tests/Broadcast.Test/ThreadWaitTests.cs diff --git a/src/Broadcast/Broadcaster.cs b/src/Broadcast/Broadcaster.cs index 90e6801..75febb9 100644 --- a/src/Broadcast/Broadcaster.cs +++ b/src/Broadcast/Broadcaster.cs @@ -87,8 +87,7 @@ public Broadcaster(ITaskStore store, ITaskProcessor processor, IScheduler schedu _context = new BroadcasterConterxt { - Id = _id, - IsRunning = true + Id = _id }; _server = new BackgroundServerProcess(_context); _server.StartNew(new BroadcasterHeartbeatDispatcher(store, _options)); @@ -164,7 +163,7 @@ protected virtual void Dispose(bool disposing) Processor.WaitAll(); Processor.Dispose(); - _context.IsRunning = false; + _context.Stop(); Store.RemoveServer(new ServerModel { Id = _id, Name = Name }); diff --git a/src/Broadcast/EventSourcing/StorageObserver.cs b/src/Broadcast/EventSourcing/StorageObserver.cs index 36d7d8c..8dc2550 100644 --- a/src/Broadcast/EventSourcing/StorageObserver.cs +++ b/src/Broadcast/EventSourcing/StorageObserver.cs @@ -12,7 +12,7 @@ namespace Broadcast.EventSourcing public class StorageObserver : IDisposable { private readonly BackgroundServerProcess _process; - private readonly WaitHandle _waitHandle; + private readonly ThreadWait _threadWait; /// /// Creates a new instance of the StorageObserver @@ -30,11 +30,11 @@ public StorageObserver(ITaskStore store, Options options) var context = new ObserverContext(new DispatcherLock(), store); _process = new BackgroundServerProcess(context); - _waitHandle = new AutoResetEvent(false); - StartScheduler(_process, options, _waitHandle); + _threadWait = new ThreadWait(); + StartScheduler(_process, options, _threadWait); } - private void StartScheduler(BackgroundServerProcess process, Options options, WaitHandle waitHandle) + private void StartScheduler(BackgroundServerProcess process, Options options, ThreadWait threadWait) { // Task.Factory.StartNew : Starts a new task that will run in a thread pool thread or may run in the same thread. // If it is ran in a thread pool thread, the thread is returned to the pool when done. @@ -46,7 +46,7 @@ private void StartScheduler(BackgroundServerProcess process, Op // This way we can ensure that the thread is a backgroundthread // Because it is only a cleanup process, it is run with the lowest ThreadPriority // - var thread = new Thread(() => ExecuteScheduler(process, options, waitHandle)) + var thread = new Thread(() => ExecuteScheduler(process, options, threadWait)) { IsBackground = true, Name = $"{nameof(StorageObserver)}", @@ -55,13 +55,13 @@ private void StartScheduler(BackgroundServerProcess process, Op thread.Start(); } - private void ExecuteScheduler(BackgroundServerProcess process, Options options, WaitHandle waitHandle) + private async void ExecuteScheduler(BackgroundServerProcess process, Options options, ThreadWait threadWait) { // loop until the waithandle is disposed - while (!waitHandle.SafeWaitHandle.IsClosed) + while (!threadWait.IsOpen) { // Delay the thread to avoid high CPU usage with the infinite loop - waitHandle.WaitOne(TimeSpan.FromMilliseconds(options.StorageCleanupInterval), true); + await threadWait.WaitOne(options.StorageCleanupInterval); // start a new dispatcher to cleanup the storage process.StartNew(new StorageCleanupDispatcher(options)); @@ -82,7 +82,7 @@ public void Start(IStorageObserver observer) /// public void Dispose() { - _waitHandle.Dispose(); + _threadWait.Dispose(); } } } diff --git a/src/Broadcast/Scheduling/ISchedulerContext.cs b/src/Broadcast/Scheduling/ISchedulerContext.cs index cf18167..c1c63be 100644 --- a/src/Broadcast/Scheduling/ISchedulerContext.cs +++ b/src/Broadcast/Scheduling/ISchedulerContext.cs @@ -9,9 +9,9 @@ namespace Broadcast.Scheduling public interface ISchedulerContext : IServerContext { /// - /// Get a boolien indicating if the is running + /// Get a indicating if the is running /// - bool IsRunning { get; set; } + ThreadWait ThreadWait { get; } /// /// Gets the elapsed time since the Scheduler has been started diff --git a/src/Broadcast/Scheduling/Scheduler.cs b/src/Broadcast/Scheduling/Scheduler.cs index 6043820..24026b8 100644 --- a/src/Broadcast/Scheduling/Scheduler.cs +++ b/src/Broadcast/Scheduling/Scheduler.cs @@ -38,10 +38,7 @@ public Scheduler(IScheduleQueue queue) _logger = LoggerFactory.Create(); _scheduleQueue = queue ?? throw new ArgumentNullException(nameof(queue)); - _context = new SchedulerContext - { - IsRunning = true - }; + _context = new SchedulerContext(); _backgroundProcess = new BackgroundServerProcess(_context); _backgroundProcess.StartNew(new SchedulerBackgroundProcess(_scheduleQueue)); @@ -96,7 +93,7 @@ protected virtual void Dispose(bool disposing) return; } - _context.IsRunning = false; + _context.ThreadWait.Dispose(); _backgroundProcess.WaitAll(); _schedulerCount--; diff --git a/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs b/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs index decc008..fb93801 100644 --- a/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs +++ b/src/Broadcast/Scheduling/SchedulerBackgroundProcess.cs @@ -10,7 +10,6 @@ namespace Broadcast.Scheduling public class SchedulerBackgroundProcess : IBackgroundDispatcher { private readonly IScheduleQueue _queue; - private readonly AutoResetEvent _waitHandle; /// /// Cretes a new instance of the SchedulerTaskDispatcher @@ -19,17 +18,15 @@ public class SchedulerBackgroundProcess : IBackgroundDispatcher /// Execute the Dispatcher to processes the scheduled tasks /// /// - public void Execute(ISchedulerContext context) + public async void Execute(ISchedulerContext context) { - while (context.IsRunning) + while (context.ThreadWait.IsOpen) { var time = context.Elapsed; foreach (var task in _queue.ToList()) @@ -45,7 +42,7 @@ public void Execute(ISchedulerContext context) } // Delay the thread to avoid high CPU usage with the infinite loop - _waitHandle.WaitOne(50, true); + await context.ThreadWait.WaitOne(50); } } } diff --git a/src/Broadcast/Scheduling/SchedulerContext.cs b/src/Broadcast/Scheduling/SchedulerContext.cs index 2176df1..87ceed6 100644 --- a/src/Broadcast/Scheduling/SchedulerContext.cs +++ b/src/Broadcast/Scheduling/SchedulerContext.cs @@ -17,12 +17,14 @@ public SchedulerContext() { _timer = new Stopwatch(); _timer.Start(); - } - /// - /// Get a boolien indicating if the is running - /// - public bool IsRunning{ get; set; } + ThreadWait = new ThreadWait(); + } + + /// + /// Get a indicating if the is running + /// + public ThreadWait ThreadWait{ get; } /// /// Gets the elapsed time since the Scheduler has been started diff --git a/src/Broadcast/Server/BroadcasterConterxt.cs b/src/Broadcast/Server/BroadcasterConterxt.cs index 4396f7e..c5edc28 100644 --- a/src/Broadcast/Server/BroadcasterConterxt.cs +++ b/src/Broadcast/Server/BroadcasterConterxt.cs @@ -1,4 +1,5 @@ - +using System.Threading; + namespace Broadcast.Server { /// @@ -7,13 +8,29 @@ namespace Broadcast.Server public class BroadcasterConterxt : IBroadcasterConterxt { /// - /// Gets a boolean indicating if the is running + /// Create a new context + /// + public BroadcasterConterxt() + { + ThreadWait = new ThreadWait(); + } + + /// + /// Gets the that stops the broadcaster /// - public bool IsRunning { get; set; } + public ThreadWait ThreadWait { get; } /// /// Gets the Id of the /// public string Id { get; set; } - } + + /// + /// End the processing thread + /// + public void Stop() + { + ThreadWait.Close(); + } + } } diff --git a/src/Broadcast/Server/BroadcasterHeartbeatDispatcher.cs b/src/Broadcast/Server/BroadcasterHeartbeatDispatcher.cs index a9bf54e..3757bba 100644 --- a/src/Broadcast/Server/BroadcasterHeartbeatDispatcher.cs +++ b/src/Broadcast/Server/BroadcasterHeartbeatDispatcher.cs @@ -32,8 +32,7 @@ public BroadcasterHeartbeatDispatcher(ITaskStore store, Options options) public async void Execute(IBroadcasterConterxt context) { // the dispatcher is created per running broadcaster - - while (context.IsRunning) + while(context.ThreadWait.IsOpen) { var model = new ServerModel { @@ -47,8 +46,8 @@ public async void Execute(IBroadcasterConterxt context) s.PropagateEvent(new StorageKey($"server:{_options.ServerName}:{context.Id}")); }); - // don't run again for at least - await Task.Delay(_options.HeartbeatInterval); + // don't run again for at least + await context.ThreadWait.WaitOne(_options.HeartbeatInterval); } } } diff --git a/src/Broadcast/Server/IBroadcasterConterxt.cs b/src/Broadcast/Server/IBroadcasterConterxt.cs index d71fcc8..a4b74e5 100644 --- a/src/Broadcast/Server/IBroadcasterConterxt.cs +++ b/src/Broadcast/Server/IBroadcasterConterxt.cs @@ -1,4 +1,5 @@ - +using System.Threading; + namespace Broadcast.Server { /// @@ -7,10 +8,10 @@ namespace Broadcast.Server public interface IBroadcasterConterxt : IServerContext { /// - /// Gets a boolean indicating if the is running + /// Gets the that stops the broadcaster /// - bool IsRunning { get; } - + ThreadWait ThreadWait { get; } + /// /// Gets the Id of the /// diff --git a/src/Broadcast/ThreadWait.cs b/src/Broadcast/ThreadWait.cs new file mode 100644 index 0000000..c6d57de --- /dev/null +++ b/src/Broadcast/ThreadWait.cs @@ -0,0 +1,60 @@ +using System; +using System.Threading.Tasks; + +namespace Broadcast +{ + /// + /// Is used to regulate threads with recurring loop + /// + public class ThreadWait : IDisposable + { + /// + /// + /// + public ThreadWait() + { + IsOpen = true; + } + + /// + /// Gets the state of the threadwait + /// + public bool IsOpen{ get; private set; } + + /// + /// Wait on the tread for the given amount of milliseconds + /// + /// + /// + public async Task WaitOne(int delay) + { + await Task.Delay(delay); + } + + /// + /// Close the threadwait + /// + public void Close() + { + IsOpen = false; + } + + /// + /// Close and dispose the TaskWait + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Close and dispose the TaskWait + /// + /// + protected virtual void Dispose(bool disposing) + { + Close(); + } + } +} diff --git a/src/Tests/Broadcast.Test/Scheduling/SchedulerBackgroundProcessTests.cs b/src/Tests/Broadcast.Test/Scheduling/SchedulerBackgroundProcessTests.cs index f15f9b6..a472d6e 100644 --- a/src/Tests/Broadcast.Test/Scheduling/SchedulerBackgroundProcessTests.cs +++ b/src/Tests/Broadcast.Test/Scheduling/SchedulerBackgroundProcessTests.cs @@ -27,15 +27,12 @@ public void SchedulerBackgroundProcess_Execute() var queue = new ScheduleQueue(); var dispatcher = new SchedulerBackgroundProcess(queue); - var ctx = new SchedulerContext - { - IsRunning = true - }; - queue.Enqueue(new SchedulerTask("id", id => { ctx.IsRunning = false; }, TimeSpan.Zero)); + var ctx = new SchedulerContext(); + queue.Enqueue(new SchedulerTask("id", id => { ctx.ThreadWait.Close(); }, TimeSpan.Zero)); dispatcher.Execute(ctx); - Assert.IsFalse(ctx.IsRunning); + Assert.IsFalse(ctx.ThreadWait.IsOpen); } [Test] @@ -44,11 +41,9 @@ public void SchedulerBackgroundProcess_Execute_Dequeu() var queue = new ScheduleQueue(); var dispatcher = new SchedulerBackgroundProcess(queue); - var ctx = new SchedulerContext - { - IsRunning = true - }; - queue.Enqueue(new SchedulerTask("id", id => { ctx.IsRunning = false; }, TimeSpan.Zero)); + var ctx = new SchedulerContext(); + + queue.Enqueue(new SchedulerTask("id", id => { ctx.ThreadWait.Close(); }, TimeSpan.Zero)); dispatcher.Execute(ctx); @@ -61,14 +56,12 @@ public void SchedulerBackgroundProcess_Execute_CheckTime() var queue = new ScheduleQueue(); var dispatcher = new SchedulerBackgroundProcess(queue); - var ctx = new SchedulerContext - { - IsRunning = true - }; + var ctx = new SchedulerContext(); + queue.Enqueue(new SchedulerTask("id1", id => { }, TimeSpan.FromMinutes(10))); queue.Enqueue(new SchedulerTask("id2", id => { }, TimeSpan.Zero)); queue.Enqueue(new SchedulerTask("id3", id => { }, TimeSpan.Zero)); - queue.Enqueue(new SchedulerTask("id4", id => { ctx.IsRunning = false; }, TimeSpan.Zero)); + queue.Enqueue(new SchedulerTask("id4", id => { ctx.ThreadWait.Close(); }, TimeSpan.Zero)); dispatcher.Execute(ctx); diff --git a/src/Tests/Broadcast.Test/Scheduling/SchedulerContextTests.cs b/src/Tests/Broadcast.Test/Scheduling/SchedulerContextTests.cs index 741e5e5..4111b43 100644 --- a/src/Tests/Broadcast.Test/Scheduling/SchedulerContextTests.cs +++ b/src/Tests/Broadcast.Test/Scheduling/SchedulerContextTests.cs @@ -21,11 +21,18 @@ public void SchedulerContext_Elapsed() Assert.Greater(ctx.Elapsed, TimeSpan.Zero); } + [Test] + public void SchedulerContext_ThreadWait() + { + var ctx = new SchedulerContext(); + Assert.IsNotNull(ctx.ThreadWait); + } + [Test] - public void SchedulerContext_IsRunning() + public void SchedulerContext_ThreadWait_IsOpen() { var ctx = new SchedulerContext(); - Assert.IsFalse(ctx.IsRunning); + Assert.IsTrue(ctx.ThreadWait.IsOpen); } } } diff --git a/src/Tests/Broadcast.Test/Server/BroadcasterHeartbeatDispatcherTests.cs b/src/Tests/Broadcast.Test/Server/BroadcasterHeartbeatDispatcherTests.cs index 810704b..68efb51 100644 --- a/src/Tests/Broadcast.Test/Server/BroadcasterHeartbeatDispatcherTests.cs +++ b/src/Tests/Broadcast.Test/Server/BroadcasterHeartbeatDispatcherTests.cs @@ -42,11 +42,10 @@ public void BroadcasterHeartbeatDispatcher_Execute() }; var context = new BroadcasterConterxt { - IsRunning = true, Id = "1" }; var storage = new Mock(); - storage.Setup(exp => exp.Storage(It.IsAny>())).Callback(() => context.IsRunning = false); + storage.Setup(exp => exp.Storage(It.IsAny>())).Callback(() => context.Stop()); var dispatcher = new BroadcasterHeartbeatDispatcher(storage.Object, options); dispatcher.Execute(context); @@ -64,13 +63,12 @@ public void BroadcasterHeartbeatDispatcher_Execute_SetStorage() }; var context = new BroadcasterConterxt { - IsRunning = true, Id = "1" }; var storage = new Mock(); var store = new TaskStore(storage.Object); - storage.Setup(exp => exp.Set(It.IsAny(), It.IsAny())).Callback(() => context.IsRunning = false); + storage.Setup(exp => exp.Set(It.IsAny(), It.IsAny())).Callback(() => context.Stop()); var dispatcher = new BroadcasterHeartbeatDispatcher(store, options); dispatcher.Execute(context); @@ -88,13 +86,12 @@ public void BroadcasterHeartbeatDispatcher_Execute_PropagateEvent() }; var context = new BroadcasterConterxt { - IsRunning = true, Id = "1" }; var storage = new Mock(); var store = new TaskStore(storage.Object); - storage.Setup(exp => exp.Set(It.IsAny(), It.IsAny())).Callback(() => context.IsRunning = false); + storage.Setup(exp => exp.Set(It.IsAny(), It.IsAny())).Callback(() => context.Stop()); var dispatcher = new BroadcasterHeartbeatDispatcher(store, options); dispatcher.Execute(context); diff --git a/src/Tests/Broadcast.Test/ThreadWaitTests.cs b/src/Tests/Broadcast.Test/ThreadWaitTests.cs new file mode 100644 index 0000000..2c3046b --- /dev/null +++ b/src/Tests/Broadcast.Test/ThreadWaitTests.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using System.Threading.Tasks; +using NUnit.Framework; + +namespace Broadcast.Test +{ + public class ThreadWaitTests + { + [Test] + public void ThreadWait_ctor() + { + Assert.DoesNotThrow(() => new ThreadWait()); + } + + [Test] + public void ThreadWait_IsOpen() + { + Assert.IsTrue(new ThreadWait().IsOpen); + } + + [Test] + public async Task ThreadWait_WaitOne() + { + var sw = new Stopwatch(); + var threadWait = new ThreadWait(); + + sw.Start(); + await threadWait.WaitOne(50); + + sw.Stop(); + Assert.Greater(sw.ElapsedMilliseconds, 50); + } + + [Test] + public void ThreadWait_Close() + { + var threadWait = new ThreadWait(); + threadWait.Close(); + + Assert.IsFalse(threadWait.IsOpen); + } + + [Test] + public void ThreadWait_Dispose() + { + var threadWait = new ThreadWait(); + threadWait.Dispose(); + + Assert.IsFalse(threadWait.IsOpen); + } + } +} From d71dc2d25b951d60e15d77ad6e8b40576cfaa7dc Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 23 Nov 2021 22:35:27 +0100 Subject: [PATCH 63/92] Use ConfigureAwait on Delay --- src/Broadcast/ThreadWait.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Broadcast/ThreadWait.cs b/src/Broadcast/ThreadWait.cs index c6d57de..71fe843 100644 --- a/src/Broadcast/ThreadWait.cs +++ b/src/Broadcast/ThreadWait.cs @@ -28,7 +28,7 @@ public ThreadWait() /// public async Task WaitOne(int delay) { - await Task.Delay(delay); + await Task.Delay(delay).ConfigureAwait(false); } /// From 1f67af51de4b876bfd247194af879b496e885459 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 25 Nov 2021 06:48:18 +0100 Subject: [PATCH 64/92] Behaviour tests for setup with multiple servers --- .../Behaviour/SetupMultipleServersTests.cs | 64 +++++++++++++++++-- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupMultipleServersTests.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupMultipleServersTests.cs index e91acda..92d69da 100644 --- a/src/Tests/Broadcast.Integration.Test/Behaviour/SetupMultipleServersTests.cs +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/SetupMultipleServersTests.cs @@ -9,33 +9,85 @@ namespace Broadcast.Integration.Test.Behaviour { - public class SetupMultipleServersTests : BDTestBase + [SingleThreaded] + [Category("Integration")] + public class SetupMultipleServersTests : BDTestBase { + [SetUp] + public void Setup() + { + TestTask.Count = 0; + } + + [Test] + public void AddTask_SetupMultipleServers_ExecuteTasksOnce() + { + WithContext(context => + Given(() => CreateStore(context)) + .And(() => AddTask(context).Wait()) + .When(() => StartMultipleServers(context).Wait()) + .Then(() => TaskIsProcessedOnce()) + .BDTest() + ); + } + [Test] - public void SetupMultipleServers_ExecuteTasksOnce() + public void ScheduleTask_SetupMultipleServers_ExecuteTasksOnce() { WithContext(context => Given(() => CreateStore(context)) - .And(() => ScheduleTasks(context).Wait()) + .And(() => ScheduleTask(context).Wait()) .When(() => StartMultipleServers(context).Wait()) .Then(() => TaskIsProcessedOnce()) .BDTest() ); } - public void CreateStore(BdContext context) + [Test] + public void SetupMultipleServers_AddTask_ExecuteTasksOnce() + { + WithContext(context => + Given(() => CreateStore(context)) + .And(() => StartMultipleServers(context).Wait()) + .When(() => AddTask(context).Wait()) + .Then(() => TaskIsProcessedOnce()) + .BDTest() + ); + } + + [Test] + public void SetupMultipleServers_ScheduleTask_ExecuteTasksOnce() + { + WithContext(context => + Given(() => CreateStore(context)) + .And(() => StartMultipleServers(context).Wait()) + .When(() => ScheduleTask(context).Wait()) + .Then(() => TaskIsProcessedOnce()) + .BDTest() + ); + } + + public void CreateStore(BdContext context) { context.Store = new TaskStore(new InmemoryStorage()); } - private BdContext ScheduleTasks(BdContext context) + private BdContext ScheduleTask(BdContext context) { var client = new BroadcastingClient(context.Store); - client.Send(() => TestTask.Add()); + client.Schedule(() => TestTask.Add(), TimeSpan.FromMilliseconds(50)); return context; } + private BdContext AddTask(BdContext context) + { + var client = new BroadcastingClient(context.Store); + client.Send(() => TestTask.Add()); + + return context; + } + public BdContext StartMultipleServers(BdContext context) { context.Context.Add("store1", new Broadcaster(context.Store)); From 9f8379f1c709e26e91fa3fe67a9171ab09ad30df Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 25 Nov 2021 11:01:02 +0100 Subject: [PATCH 65/92] Badges for SonarCloud and Codacy --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 9b36198..f961f17 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,10 @@ [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=WickedFlame_Broadcast&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=WickedFlame_Broadcast) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=WickedFlame_Broadcast&metric=coverage)](https://sonarcloud.io/summary/new_code?id=WickedFlame_Broadcast) +[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=WickedFlame_Broadcast&metric=ncloc)](https://sonarcloud.io/summary/new_code?id=WickedFlame_Broadcast) + +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9f04469804014684ac6c1e91bed72e5e)](https://www.codacy.com/gh/WickedFlame/Broadcast/dashboard?utm_source=github.com&utm_medium=referral&utm_content=WickedFlame/Broadcast&utm_campaign=Badge_Grade) Simple and easy to use background task processing and message queue for .NET From 877f3a5eabb33996a39748eac998c78555963fa7 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 25 Nov 2021 11:38:12 +0100 Subject: [PATCH 66/92] Use dotnet-sonarscanner instead of builtin scanner --- .travis.yml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 47c900a..3bf714f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,22 +16,28 @@ notifications: on_success: never #[always|never|change] # default: change on_failure: always #[always|never|change] # default: always +before_script: + - export PATH="$PATH:$HOME/.dotnet/tools" + install: + - dotnet tool install --global dotnet-sonarscanner - dotnet restore - nvm install 10.0.0 - nvm use 10.0.0 script: + - dotnet sonarscanner begin /k:"WickedFlame_Broadcast" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.login="$SONAR_KEY" /d:sonar.language="cs" /d:sonar.exclusions="**/bin/**/*,**/obj/**/*" /d:sonar.cs.opencover.reportsPaths="lcov.opencover.xml" || true - dotnet build --configuration NetCore # - dotnet test # - dotnet test Tests/DataImporter.Tests/DataImporter.Tests.csproj + - dotnet sonarscanner end /d:sonar.login="$SONAR_KEY" || true -addons: - sonarcloud: - organization: "wickedflame" +#addons: +# sonarcloud: +# organization: "wickedflame" # token: # secure: "" # encrypted value of your token -script: +#script: # the following command line builds the project, runs the tests with coverage and then execute the SonarCloud analysis - - sonar-scanner \ No newline at end of file +# - sonar-scanner \ No newline at end of file From 2b71d15cddde31af348e57277fa4904d9e46aa99 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 25 Nov 2021 18:40:49 +0100 Subject: [PATCH 67/92] Add build for github actions --- .github/workflows/build.yml | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..6bc924c --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,48 @@ +name: Build +on: + push: + branches: + - master + - dev + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + name: Build + runs-on: windows-latest + steps: + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 1.11 + - uses: actions/checkout@v2 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - name: Cache SonarCloud packages + uses: actions/cache@v1 + with: + path: ~\sonar\cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + - name: Cache SonarCloud scanner + id: cache-sonar-scanner + uses: actions/cache@v1 + with: + path: .\.sonar\scanner + key: ${{ runner.os }}-sonar-scanner + restore-keys: ${{ runner.os }}-sonar-scanner + - name: Install SonarCloud scanner + if: steps.cache-sonar-scanner.outputs.cache-hit != 'true' + shell: powershell + run: | + New-Item -Path .\.sonar\scanner -ItemType Directory + dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner + - name: Build and analyze + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + shell: powershell + run: | + .\.sonar\scanner\dotnet-sonarscanner begin /k:"WickedFlame_Broadcast" /o:"wickedflame" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" + dotnet build + .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" \ No newline at end of file From dc551499ef88b77e0e8d33a6f0b34cbf6ad40ff1 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 25 Nov 2021 18:48:03 +0100 Subject: [PATCH 68/92] Removed sonar-project.properties --- sonar-project.properties | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 sonar-project.properties diff --git a/sonar-project.properties b/sonar-project.properties deleted file mode 100644 index e5ccc99..0000000 --- a/sonar-project.properties +++ /dev/null @@ -1,15 +0,0 @@ -sonar.projectKey=WickedFlame_Broadcast -sonar.organization=wickedflame - -# This is the name and version displayed in the SonarCloud UI. -#sonar.projectName=Broadcast -#sonar.projectVersion=1.0 - -# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. -#sonar.sources=. - -# Encoding of the source code. Default is default system encoding -#sonar.sourceEncoding=UTF-8 - -#sonar.exclusions=**\bin\**,**\OurProject.Web\Reports\**,**\Content\js\** -sonar.exclusions=**\bin\**,**\*.js \ No newline at end of file From 5679604fe2607b92b7bf71d9ccf6fab2fddbfd43 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 25 Nov 2021 19:57:16 +0100 Subject: [PATCH 69/92] Add coverlet.collector to test projects --- .github/workflows/build.yml | 1 + .../Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj | 4 ++++ .../Broadcast.Integration.Test.csproj | 4 ++++ .../Broadcast.Storage.Integration.Test.csproj | 5 ++++- .../Broadcast.Storage.Redis.Integration.Test.csproj | 5 ++++- .../Broadcast.Storage.Redis.Test.csproj | 4 ++++ src/Tests/Broadcast.Test/Broadcast.Test.csproj | 4 ++++ 7 files changed, 25 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6bc924c..d123aa4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,4 +45,5 @@ jobs: run: | .\.sonar\scanner\dotnet-sonarscanner begin /k:"WickedFlame_Broadcast" /o:"wickedflame" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" dotnet build + dotnet test .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" \ No newline at end of file diff --git a/src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj b/src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj index f1b0bd3..d6649e4 100644 --- a/src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj +++ b/src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj @@ -9,6 +9,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj b/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj index 32377a7..dfe8cf6 100644 --- a/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj +++ b/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj @@ -10,6 +10,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj b/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj index 71443fe..f01ea07 100644 --- a/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj +++ b/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj @@ -13,7 +13,10 @@ - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj b/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj index 7969a32..dc13f4a 100644 --- a/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj +++ b/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj @@ -17,7 +17,10 @@ - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj b/src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj index 133f712..10fc246 100644 --- a/src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj +++ b/src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj @@ -9,6 +9,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Tests/Broadcast.Test/Broadcast.Test.csproj b/src/Tests/Broadcast.Test/Broadcast.Test.csproj index 0b4b140..82acff0 100644 --- a/src/Tests/Broadcast.Test/Broadcast.Test.csproj +++ b/src/Tests/Broadcast.Test/Broadcast.Test.csproj @@ -9,6 +9,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + From 02222779284eae643685c5a0a5d03b89f8b872ed Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 25 Nov 2021 20:55:36 +0100 Subject: [PATCH 70/92] Testcoverage for sonar --- .github/workflows/build.yml | 2 +- coverlet.runsettings | 22 ++++++++++++++++++++++ sonar-project.properties | 20 ++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 coverlet.runsettings create mode 100644 sonar-project.properties diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d123aa4..5d0b08a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,5 +45,5 @@ jobs: run: | .\.sonar\scanner\dotnet-sonarscanner begin /k:"WickedFlame_Broadcast" /o:"wickedflame" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" dotnet build - dotnet test + dotnet test --collect:"XPlat Code Coverage" -r:TestResults .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" \ No newline at end of file diff --git a/coverlet.runsettings b/coverlet.runsettings new file mode 100644 index 0000000..5d41179 --- /dev/null +++ b/coverlet.runsettings @@ -0,0 +1,22 @@ + + + + + + + json,cobertura,lcov,teamcity,opencover + [*.tests?]* + Broadcast,Broadcast.Dashboard,Broadcast.Storage.Redis + Obsolete,GeneratedCodeAttribute,CompilerGeneratedAttribute + **/dir1/class1.cs,**/dir2/*.cs,**/dir3/**/*.cs, + ../dir1/,../dir2/, + false + true + true + true + false + + + + + \ No newline at end of file diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..e38e691 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,20 @@ +#sonar.organization=organization_is_in_sonarcloud +#sonar.projectKey=key_is_displayed_in_sonarcloud +#sonar.projectName=your_project_name_here +#sonar.projectVersion=latest +#sonar.links.homepage=[repo URL] +#sonar.links.scm=[repo URL] + +sonar.sources=src +sonar.exclusions=node_modules/**/*, reports/**/* + +#sonar.testExecutionReportPaths=reports/test-reporter.xml +#sonar.javascript.lcov.reportPaths=reports/lcov.info +#sonar.test.inclusions=**/*.test.js + +sonar.language=js +sonar.sourceEncoding=UTF-8 +sonar.host.url=https://sonarcloud.io + +sonar.cs.analyzeGeneratedCode=true +sonar.cs.vscoveragexml.reportsPaths=TestResults/*/coverage.cobertura.xml From 6291a7dab4b1502d960fe48cb41a0afd71de406a Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 25 Nov 2021 21:09:37 +0100 Subject: [PATCH 71/92] Exclude integrationtests from Testcoverage --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5d0b08a..156bd06 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,5 +45,7 @@ jobs: run: | .\.sonar\scanner\dotnet-sonarscanner begin /k:"WickedFlame_Broadcast" /o:"wickedflame" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" dotnet build - dotnet test --collect:"XPlat Code Coverage" -r:TestResults + dotnet test src/Tests/Broadcast.Test/Broadcast.Test.csproj --collect:"XPlat Code Coverage" -r:TestResults + dotnet test src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj --collect:"XPlat Code Coverage" -r:TestResults + dotnet test src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj --collect:"XPlat Code Coverage" -r:TestResults .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" \ No newline at end of file From bbc4f3fbfcbdef2e24967d83812651c41acf9b56 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 25 Nov 2021 21:18:35 +0100 Subject: [PATCH 72/92] Testresults via parameters --- .github/workflows/build.yml | 2 +- sonar-project.properties | 20 -------------------- 2 files changed, 1 insertion(+), 21 deletions(-) delete mode 100644 sonar-project.properties diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 156bd06..ce27bc5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,7 +43,7 @@ jobs: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} shell: powershell run: | - .\.sonar\scanner\dotnet-sonarscanner begin /k:"WickedFlame_Broadcast" /o:"wickedflame" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" + .\.sonar\scanner\dotnet-sonarscanner begin /k:"WickedFlame_Broadcast" /o:"wickedflame" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths="TestResults/*/coverage.cobertura.xml" dotnet build dotnet test src/Tests/Broadcast.Test/Broadcast.Test.csproj --collect:"XPlat Code Coverage" -r:TestResults dotnet test src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj --collect:"XPlat Code Coverage" -r:TestResults diff --git a/sonar-project.properties b/sonar-project.properties deleted file mode 100644 index e38e691..0000000 --- a/sonar-project.properties +++ /dev/null @@ -1,20 +0,0 @@ -#sonar.organization=organization_is_in_sonarcloud -#sonar.projectKey=key_is_displayed_in_sonarcloud -#sonar.projectName=your_project_name_here -#sonar.projectVersion=latest -#sonar.links.homepage=[repo URL] -#sonar.links.scm=[repo URL] - -sonar.sources=src -sonar.exclusions=node_modules/**/*, reports/**/* - -#sonar.testExecutionReportPaths=reports/test-reporter.xml -#sonar.javascript.lcov.reportPaths=reports/lcov.info -#sonar.test.inclusions=**/*.test.js - -sonar.language=js -sonar.sourceEncoding=UTF-8 -sonar.host.url=https://sonarcloud.io - -sonar.cs.analyzeGeneratedCode=true -sonar.cs.vscoveragexml.reportsPaths=TestResults/*/coverage.cobertura.xml From d87fb4a076c91be98b2aae0c59b21d15688383eb Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 25 Nov 2021 21:57:47 +0100 Subject: [PATCH 73/92] Use coverlet.msbuild instead of coverlet.collector --- .github/workflows/build.yml | 8 ++++---- .../Broadcast.Dashboard.Test.csproj | 2 +- .../Broadcast.Integration.Test.csproj | 4 ---- .../Broadcast.Storage.Integration.Test.csproj | 4 ---- .../Broadcast.Storage.Redis.Integration.Test.csproj | 4 ---- .../Broadcast.Storage.Redis.Test.csproj | 2 +- src/Tests/Broadcast.Test/Broadcast.Test.csproj | 2 +- 7 files changed, 7 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ce27bc5..0b35e7e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,9 +43,9 @@ jobs: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} shell: powershell run: | - .\.sonar\scanner\dotnet-sonarscanner begin /k:"WickedFlame_Broadcast" /o:"wickedflame" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths="TestResults/*/coverage.cobertura.xml" + .\.sonar\scanner\dotnet-sonarscanner begin /k:"WickedFlame_Broadcast" /o:"wickedflame" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths="src/Tests/*/coverage.opencover.xml" dotnet build - dotnet test src/Tests/Broadcast.Test/Broadcast.Test.csproj --collect:"XPlat Code Coverage" -r:TestResults - dotnet test src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj --collect:"XPlat Code Coverage" -r:TestResults - dotnet test src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj --collect:"XPlat Code Coverage" -r:TestResults + dotnet test src/Tests/Broadcast.Test/Broadcast.Test.csproj /p:CollectCoverage=true /p:CoverletOutputFormat=opencover + dotnet test src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj /p:CollectCoverage=true /p:CoverletOutputFormat=opencover + dotnet test src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj /p:CollectCoverage=true /p:CoverletOutputFormat=opencover .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" \ No newline at end of file diff --git a/src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj b/src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj index d6649e4..c85c342 100644 --- a/src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj +++ b/src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj b/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj index dfe8cf6..32377a7 100644 --- a/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj +++ b/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj @@ -10,10 +10,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj b/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj index f01ea07..04d940a 100644 --- a/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj +++ b/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj @@ -13,10 +13,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj b/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj index dc13f4a..36f8a36 100644 --- a/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj +++ b/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj @@ -17,10 +17,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj b/src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj index 10fc246..7338b1a 100644 --- a/src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj +++ b/src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Tests/Broadcast.Test/Broadcast.Test.csproj b/src/Tests/Broadcast.Test/Broadcast.Test.csproj index 82acff0..bd978d0 100644 --- a/src/Tests/Broadcast.Test/Broadcast.Test.csproj +++ b/src/Tests/Broadcast.Test/Broadcast.Test.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From d7ab755f76b3e8477cd219aed1857aac4eed2a33 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Thu, 25 Nov 2021 22:17:18 +0100 Subject: [PATCH 74/92] Path to cover xml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0b35e7e..d9a83a6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,7 +43,7 @@ jobs: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} shell: powershell run: | - .\.sonar\scanner\dotnet-sonarscanner begin /k:"WickedFlame_Broadcast" /o:"wickedflame" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths="src/Tests/*/coverage.opencover.xml" + .\.sonar\scanner\dotnet-sonarscanner begin /k:"WickedFlame_Broadcast" /o:"wickedflame" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="src/Tests/Broadcast.Test/coverage.opencover.xml,src/Tests/Broadcast.Dashboard.Test/coverage.opencover.xml,src/Tests/Broadcast.Storage.Redis.Test/coverage.opencover.xml" dotnet build dotnet test src/Tests/Broadcast.Test/Broadcast.Test.csproj /p:CollectCoverage=true /p:CoverletOutputFormat=opencover dotnet test src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj /p:CollectCoverage=true /p:CoverletOutputFormat=opencover From 199ec93d4624d8fc1312390252e9836b07751c51 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Fri, 26 Nov 2021 22:21:27 +0100 Subject: [PATCH 75/92] Update Polaroider --- .../Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj | 2 +- .../Broadcast.Storage.Integration.Test.csproj | 2 +- .../Broadcast.Storage.Redis.Integration.Test.csproj | 2 +- .../Broadcast.Storage.Redis.Test.csproj | 2 +- src/Tests/Broadcast.Test/Broadcast.Test.csproj | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj b/src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj index c85c342..c32c785 100644 --- a/src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj +++ b/src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj @@ -17,7 +17,7 @@ - + diff --git a/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj b/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj index 04d940a..ab7692a 100644 --- a/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj +++ b/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj b/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj index 36f8a36..56f98f7 100644 --- a/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj +++ b/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj @@ -17,7 +17,7 @@ - + diff --git a/src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj b/src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj index 7338b1a..9116aeb 100644 --- a/src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj +++ b/src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj @@ -17,7 +17,7 @@ - + diff --git a/src/Tests/Broadcast.Test/Broadcast.Test.csproj b/src/Tests/Broadcast.Test/Broadcast.Test.csproj index bd978d0..1d685fe 100644 --- a/src/Tests/Broadcast.Test/Broadcast.Test.csproj +++ b/src/Tests/Broadcast.Test/Broadcast.Test.csproj @@ -17,7 +17,7 @@ - + From d37446be1bc0fb3296ecbd41cab1ea35f80db4ec Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sat, 4 Dec 2021 21:46:47 +0100 Subject: [PATCH 76/92] Storage cleanup fix --- src/Broadcast/EventSourcing/StorageObserver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Broadcast/EventSourcing/StorageObserver.cs b/src/Broadcast/EventSourcing/StorageObserver.cs index 8dc2550..949f7b0 100644 --- a/src/Broadcast/EventSourcing/StorageObserver.cs +++ b/src/Broadcast/EventSourcing/StorageObserver.cs @@ -58,7 +58,7 @@ private void StartScheduler(BackgroundServerProcess process, Op private async void ExecuteScheduler(BackgroundServerProcess process, Options options, ThreadWait threadWait) { // loop until the waithandle is disposed - while (!threadWait.IsOpen) + while (threadWait.IsOpen) { // Delay the thread to avoid high CPU usage with the infinite loop await threadWait.WaitOne(options.StorageCleanupInterval); From 0d1420718c1aac3467183423750aa1753719fbee Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sat, 4 Dec 2021 21:48:10 +0100 Subject: [PATCH 77/92] Refactored options to processoroptions --- Broadcast.sln | 5 +++-- .../AppBuilderExtensions.cs | 5 +++-- .../BroadcastApplicationBuilderExtensions.cs | 4 ++-- src/Broadcast/BroadcastServer.cs | 2 +- src/Broadcast/Broadcaster.cs | 10 +++++----- src/Broadcast/Configuration/Options.cs | 15 ++------------- .../Configuration/ProcessorOptions.cs | 18 ++++++++++++++++++ src/Broadcast/EventSourcing/TaskStore.cs | 3 +-- src/Broadcast/Processing/IProcessorContext.cs | 2 +- src/Broadcast/Processing/ProcessorContext.cs | 6 +++--- src/Broadcast/Processing/TaskProcessor.cs | 2 +- .../Server/BroadcasterHeartbeatDispatcher.cs | 8 ++++---- src/Broadcast/Server/ServerModel.cs | 2 ++ src/Broadcast/ServerConfigurationExtensions.cs | 2 +- src/Broadcast/Setup/ServerSetupExtensions.cs | 14 +++++++++++++- src/Tests/Broadcast.AspNet.TestApp/Startup.cs | 2 +- .../Broadcast.AspNetCore.TestApp/Startup.cs | 10 +++++++--- .../Configuration/OptionsTests.cs | 14 ++++++++++---- .../ServerHeartbeatSubscriberTests.cs | 3 ++- .../EventSourcing/TaskStoreTests.cs | 3 ++- .../Processing/TaskProcessorTests.cs | 12 ++++++------ .../BroadcasterHeartbeatDispatcherTests.cs | 10 +++++----- .../Setup/ServerSetupExtensionsTests.cs | 8 ++++---- 23 files changed, 97 insertions(+), 63 deletions(-) create mode 100644 src/Broadcast/Configuration/ProcessorOptions.cs diff --git a/Broadcast.sln b/Broadcast.sln index eb8062e..0318afc 100644 --- a/Broadcast.sln +++ b/Broadcast.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29509.3 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Broadcast", "src\Broadcast\Broadcast.csproj", "{88E7BB4F-B2BD-4BB9-99D2-66CDDD7095DA}" EndProject @@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .travis.yml = .travis.yml appveyor.yml = appveyor.yml src\Broadcast.snk = src\Broadcast.snk + .github\workflows\build.yml = .github\workflows\build.yml License.txt = License.txt README.md = README.md sonar-project.properties = sonar-project.properties diff --git a/src/Broadcast.Dashboard/AppBuilderExtensions.cs b/src/Broadcast.Dashboard/AppBuilderExtensions.cs index a737178..6568eb6 100644 --- a/src/Broadcast.Dashboard/AppBuilderExtensions.cs +++ b/src/Broadcast.Dashboard/AppBuilderExtensions.cs @@ -40,13 +40,14 @@ public static IAppBuilder UseBroadcastServer(this IAppBuilder builder, Action() ?? new InmemoryStorage(); var store = serverSetup.Resolve() ?? new TaskStore(options, storage); - var processor = new TaskProcessor(store, options); + var processorOptions = serverSetup.Resolve() ?? new ProcessorOptions(); + var processor = new TaskProcessor(store, processorOptions); var scheduler = new Scheduler(); TaskStore.Setup(() => store); BroadcastServer.Setup(c => - c.AddOptions(options) + c.AddOptions(processorOptions) .AddProcessor(processor) .AddScheduler(scheduler) .AddTaskStore(store) diff --git a/src/Broadcast.Dashboard/BroadcastApplicationBuilderExtensions.cs b/src/Broadcast.Dashboard/BroadcastApplicationBuilderExtensions.cs index ed2513c..2746313 100644 --- a/src/Broadcast.Dashboard/BroadcastApplicationBuilderExtensions.cs +++ b/src/Broadcast.Dashboard/BroadcastApplicationBuilderExtensions.cs @@ -14,7 +14,7 @@ namespace Broadcast { public static class BroadcastApplicationBuilderExtensions { - public static IApplicationBuilder UseBroadcastServer(this IApplicationBuilder app, Options options = null) + public static IApplicationBuilder UseBroadcastServer(this IApplicationBuilder app, ProcessorOptions options = null) { if (app == null) { @@ -29,7 +29,7 @@ public static IApplicationBuilder UseBroadcastServer(this IApplicationBuilder ap #endif // use TaskStore.Default if the services.AddBroadcast() is not configured var storage = services.GetService() ?? TaskStore.Default; - options ??= services.GetService() ?? new Options(); + options ??= services.GetService() ?? new ProcessorOptions(); var processor = new TaskProcessor(storage, options); var scheduler = new Scheduler(); diff --git a/src/Broadcast/BroadcastServer.cs b/src/Broadcast/BroadcastServer.cs index 437f1f0..18e503f 100644 --- a/src/Broadcast/BroadcastServer.cs +++ b/src/Broadcast/BroadcastServer.cs @@ -37,7 +37,7 @@ public static void Setup(Action config) config(serverSetup); var store = serverSetup.Get() ?? TaskStore.Default; - var options = serverSetup.Get() ?? new Options(); + var options = serverSetup.Get() ?? new ProcessorOptions(); var processor = serverSetup.Get() ?? new TaskProcessor(store, options); var scheduler = serverSetup.Get() ?? new Scheduler(); diff --git a/src/Broadcast/Broadcaster.cs b/src/Broadcast/Broadcaster.cs index 75febb9..7a147b9 100644 --- a/src/Broadcast/Broadcaster.cs +++ b/src/Broadcast/Broadcaster.cs @@ -18,7 +18,7 @@ namespace Broadcast /// public class Broadcaster : IBroadcaster { - private readonly Options _options; + private readonly ProcessorOptions _options; private readonly ILogger _logger; private readonly string _id = Guid.NewGuid().ToString(); private readonly BroadcasterConterxt _context; @@ -36,7 +36,7 @@ public Broadcaster() : this(TaskStore.Default) /// /// public Broadcaster(ITaskStore store) - : this(store, new Options()) + : this(store, new ProcessorOptions()) { } @@ -45,7 +45,7 @@ public Broadcaster(ITaskStore store) /// /// /// - public Broadcaster(ITaskStore store, Options options) + public Broadcaster(ITaskStore store, ProcessorOptions options) : this(store, new TaskProcessor(store, options), new Scheduler(), options) { } @@ -57,7 +57,7 @@ public Broadcaster(ITaskStore store, Options options) /// /// public Broadcaster(ITaskStore store, ITaskProcessor processor, IScheduler scheduler) - : this(store, processor, scheduler, new Options()) + : this(store, processor, scheduler, new ProcessorOptions()) { } @@ -68,7 +68,7 @@ public Broadcaster(ITaskStore store, ITaskProcessor processor, IScheduler schedu /// /// /// - public Broadcaster(ITaskStore store, ITaskProcessor processor, IScheduler scheduler, Options options) + public Broadcaster(ITaskStore store, ITaskProcessor processor, IScheduler scheduler, ProcessorOptions options) { _logger = LoggerFactory.Create(); _logger.Write($"Starting new Broadcaster {options.ServerName}:{_id}"); diff --git a/src/Broadcast/Configuration/Options.cs b/src/Broadcast/Configuration/Options.cs index 6329e68..2fae9e1 100644 --- a/src/Broadcast/Configuration/Options.cs +++ b/src/Broadcast/Configuration/Options.cs @@ -4,28 +4,17 @@ namespace Broadcast.Configuration { /// - /// The options used by the Server + /// The options used by the Storage /// public class Options { - /// - /// Gets or sets the designated name of the server. - /// Each gets an individual Id that is generated with each creation. - /// - public string ServerName { get; set; } = Environment.MachineName; - - /// - /// Gets or set the milliseconds that the Hearbeat is propagated to the - /// - public int HeartbeatInterval { get; set; } = (int)TimeSpan.FromMinutes(1).TotalMilliseconds; - /// /// Gets or set the milliseconds that the storage cleanup task is run. Defaults to each minute (60000 ms) /// public int StorageCleanupInterval { get; set; } = (int)TimeSpan.FromMinutes(1).TotalMilliseconds; /// - /// Gets or set the duration that a task is stored after completition or failiure. Defaults to each hour + /// Gets or set the duration in milliseconds that a task is stored after completition or failiure. Defaults to each hour /// public int StorageLifetimeDuration { get; set; } = (int)TimeSpan.FromMinutes(60).TotalMilliseconds; } diff --git a/src/Broadcast/Configuration/ProcessorOptions.cs b/src/Broadcast/Configuration/ProcessorOptions.cs new file mode 100644 index 0000000..46ad93e --- /dev/null +++ b/src/Broadcast/Configuration/ProcessorOptions.cs @@ -0,0 +1,18 @@ +using System; + +namespace Broadcast.Configuration +{ + public class ProcessorOptions + { + /// + /// Gets or sets the designated name of the server. + /// Each gets an individual Id that is generated with each creation. + /// + public string ServerName { get; set; } = Environment.MachineName; + + /// + /// Gets or set the milliseconds that the Hearbeat is propagated to the + /// + public int HeartbeatInterval { get; set; } = (int)TimeSpan.FromMinutes(1).TotalMilliseconds; + } +} diff --git a/src/Broadcast/EventSourcing/TaskStore.cs b/src/Broadcast/EventSourcing/TaskStore.cs index 3826c4f..0b2821f 100644 --- a/src/Broadcast/EventSourcing/TaskStore.cs +++ b/src/Broadcast/EventSourcing/TaskStore.cs @@ -259,8 +259,7 @@ public void PropagateServer(ServerModel server) // cleanup dead servers // servers are propagated each HeartbeatInterval // we remove servers that are not propagated at the double time - var expiration = DateTime.Now.Subtract(TimeSpan.FromMilliseconds(_options.HeartbeatInterval * 2)); - var deadServers = _registeredServers.Where(item => item.Value.Heartbeat < expiration).Select(item => item.Key).ToList(); + var deadServers = _registeredServers.Where(item => item.Value.Expiration < DateTime.Now).Select(item => item.Key).ToList(); foreach (var key in deadServers) { _registeredServers.Remove(key); diff --git a/src/Broadcast/Processing/IProcessorContext.cs b/src/Broadcast/Processing/IProcessorContext.cs index 22cd6ed..e8f0b7c 100644 --- a/src/Broadcast/Processing/IProcessorContext.cs +++ b/src/Broadcast/Processing/IProcessorContext.cs @@ -12,7 +12,7 @@ public interface IProcessorContext : IServerContext /// /// Gets the /// - Options Options { get; set; } + ProcessorOptions Options { get; set; } /// /// Gets the associated with the diff --git a/src/Broadcast/Processing/ProcessorContext.cs b/src/Broadcast/Processing/ProcessorContext.cs index 688ab04..a02ce08 100644 --- a/src/Broadcast/Processing/ProcessorContext.cs +++ b/src/Broadcast/Processing/ProcessorContext.cs @@ -13,7 +13,7 @@ public class ProcessorContext : IProcessorContext, IServerContext /// /// public ProcessorContext(ITaskStore store) - : this(store, new Options()) + : this(store, new ProcessorOptions()) { } @@ -22,7 +22,7 @@ public ProcessorContext(ITaskStore store) /// /// /// - public ProcessorContext(ITaskStore store, Options options) + public ProcessorContext(ITaskStore store, ProcessorOptions options) { Options = options; Store = store; @@ -31,7 +31,7 @@ public ProcessorContext(ITaskStore store, Options options) /// /// Gets or sets the /// - public Options Options { get; set; } + public ProcessorOptions Options { get; set; } /// /// Gets the associated with the diff --git a/src/Broadcast/Processing/TaskProcessor.cs b/src/Broadcast/Processing/TaskProcessor.cs index ed6b737..108f461 100644 --- a/src/Broadcast/Processing/TaskProcessor.cs +++ b/src/Broadcast/Processing/TaskProcessor.cs @@ -24,7 +24,7 @@ public class TaskProcessor : ITaskProcessor, IDisposable /// /// /// - public TaskProcessor(ITaskStore store, Options options) + public TaskProcessor(ITaskStore store, ProcessorOptions options) { if (store == null) { diff --git a/src/Broadcast/Server/BroadcasterHeartbeatDispatcher.cs b/src/Broadcast/Server/BroadcasterHeartbeatDispatcher.cs index 3757bba..6bb28a8 100644 --- a/src/Broadcast/Server/BroadcasterHeartbeatDispatcher.cs +++ b/src/Broadcast/Server/BroadcasterHeartbeatDispatcher.cs @@ -1,5 +1,4 @@ using System; -using System.Threading.Tasks; using Broadcast.Configuration; using Broadcast.Storage; @@ -12,14 +11,14 @@ namespace Broadcast.Server public class BroadcasterHeartbeatDispatcher : IBackgroundDispatcher { private readonly ITaskStore _store; - private readonly Options _options; + private readonly ProcessorOptions _options; /// /// Creates a new instance of the BroadcasterHeartbeatDispatcher /// /// /// - public BroadcasterHeartbeatDispatcher(ITaskStore store, Options options) + public BroadcasterHeartbeatDispatcher(ITaskStore store, ProcessorOptions options) { _store = store ?? throw new ArgumentNullException(nameof(store)); _options = options ?? throw new ArgumentNullException(nameof(options)); @@ -38,7 +37,8 @@ public async void Execute(IBroadcasterConterxt context) { Name = _options.ServerName, Id = context.Id, - Heartbeat = DateTime.Now + Heartbeat = DateTime.Now, + Expiration = DateTime.Now.Add(TimeSpan.FromMilliseconds(_options.HeartbeatInterval * 2)) }; _store.Storage(s => { diff --git a/src/Broadcast/Server/ServerModel.cs b/src/Broadcast/Server/ServerModel.cs index 1f72170..9dc2f1e 100644 --- a/src/Broadcast/Server/ServerModel.cs +++ b/src/Broadcast/Server/ServerModel.cs @@ -21,5 +21,7 @@ public class ServerModel /// Gets or sets the Heartbeat timestamp /// public DateTime Heartbeat { get; set; } + + public DateTime Expiration { get; set; } } } diff --git a/src/Broadcast/ServerConfigurationExtensions.cs b/src/Broadcast/ServerConfigurationExtensions.cs index e3acc6c..64d6d23 100644 --- a/src/Broadcast/ServerConfigurationExtensions.cs +++ b/src/Broadcast/ServerConfigurationExtensions.cs @@ -50,7 +50,7 @@ public static ServerConfiguration AddTaskStore(this ServerConfiguration setup, I /// /// /// - public static ServerConfiguration AddOptions(this ServerConfiguration setup, Options options) + public static ServerConfiguration AddOptions(this ServerConfiguration setup, ProcessorOptions options) { setup.Add(options); return setup; diff --git a/src/Broadcast/Setup/ServerSetupExtensions.cs b/src/Broadcast/Setup/ServerSetupExtensions.cs index 6da9f1c..6e24365 100644 --- a/src/Broadcast/Setup/ServerSetupExtensions.cs +++ b/src/Broadcast/Setup/ServerSetupExtensions.cs @@ -21,7 +21,7 @@ public static IServerSetup UseTaskStore(this IServerSetup setup, ITaskStore stor } /// - /// Set the options that are used for the Server + /// Set the options that are used for the Storage /// /// /// @@ -32,6 +32,18 @@ public static IServerSetup UseOptions(this IServerSetup setup, Options options) return setup; } + /// + /// Set the options that are used for the Server + /// + /// + /// + /// + public static IServerSetup UseOptions(this IServerSetup setup, ProcessorOptions options) + { + setup.Register(options); + return setup; + } + /// /// Register a item in the Context /// diff --git a/src/Tests/Broadcast.AspNet.TestApp/Startup.cs b/src/Tests/Broadcast.AspNet.TestApp/Startup.cs index f5ec978..6c9ca36 100644 --- a/src/Tests/Broadcast.AspNet.TestApp/Startup.cs +++ b/src/Tests/Broadcast.AspNet.TestApp/Startup.cs @@ -17,7 +17,7 @@ public void Configuration(IAppBuilder app) { app.UseBroadcastServer(c => { - c.UseOptions(new Broadcast.Configuration.Options + c.UseOptions(new Broadcast.Configuration.ProcessorOptions { ServerName = "Asp.Net" }); diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Startup.cs b/src/Tests/Broadcast.AspNetCore.TestApp/Startup.cs index 1c42c61..ffe8a5b 100644 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Startup.cs +++ b/src/Tests/Broadcast.AspNetCore.TestApp/Startup.cs @@ -33,7 +33,10 @@ public void ConfigureServices(IServiceCollection services) services.AddBroadcast(c => c.UseRedisStorage("localhost:6379")); #else //services.AddBroadcast(c => c.UseTaskStore(new TaskStore())); - services.AddBroadcast(); + services.AddBroadcast(c => c.UseOptions(new Broadcast.Configuration.Options + { + StorageLifetimeDuration = (int)TimeSpan.FromMinutes(2).TotalMilliseconds + })); #endif } @@ -55,9 +58,10 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) //app.UseBroadcastServer(new Broadcast.Configuration.Options(), new TaskStore()); app.UseBroadcastServer(); - app.UseBroadcastServer(new Broadcast.Configuration.Options + app.UseBroadcastServer(new Broadcast.Configuration.ProcessorOptions { - ServerName = "test 1" + ServerName = "test 1", + }); //Server = new Broadcaster(TaskStore.Default); diff --git a/src/Tests/Broadcast.Test/Configuration/OptionsTests.cs b/src/Tests/Broadcast.Test/Configuration/OptionsTests.cs index c5bdb6b..23d72cd 100644 --- a/src/Tests/Broadcast.Test/Configuration/OptionsTests.cs +++ b/src/Tests/Broadcast.Test/Configuration/OptionsTests.cs @@ -14,16 +14,22 @@ public void Options_ctor() Assert.DoesNotThrow(() => new Options()); } + [Test] + public void ProcessorOptions_ctor() + { + Assert.DoesNotThrow(() => new ProcessorOptions()); + } + [Test] - public void Options_Property_ServerName_Default() + public void ProcessorOptions_Property_ServerName_Default() { - Assert.AreEqual(Environment.MachineName, new Options().ServerName); + Assert.AreEqual(Environment.MachineName, new ProcessorOptions().ServerName); } [Test] - public void Options_Property_HeartbeatInterval_Default() + public void ProcessorOptions_Property_HeartbeatInterval_Default() { - Assert.AreEqual(60000, new Options().HeartbeatInterval); + Assert.AreEqual(60000, new ProcessorOptions().HeartbeatInterval); } } } diff --git a/src/Tests/Broadcast.Test/EventSourcing/ServerHeartbeatSubscriberTests.cs b/src/Tests/Broadcast.Test/EventSourcing/ServerHeartbeatSubscriberTests.cs index 11aae18..d18d9f1 100644 --- a/src/Tests/Broadcast.Test/EventSourcing/ServerHeartbeatSubscriberTests.cs +++ b/src/Tests/Broadcast.Test/EventSourcing/ServerHeartbeatSubscriberTests.cs @@ -64,7 +64,8 @@ public void ServerHeartbeatSubscriber_RaiseEvent_PropagateServer() { Id = "1", Heartbeat = DateTime.Now, - Name = "test" + Name = "test", + Expiration = DateTime.Now.AddMilliseconds(1000) }; var storage = new Mock(); diff --git a/src/Tests/Broadcast.Test/EventSourcing/TaskStoreTests.cs b/src/Tests/Broadcast.Test/EventSourcing/TaskStoreTests.cs index 44d7447..bc9c362 100644 --- a/src/Tests/Broadcast.Test/EventSourcing/TaskStoreTests.cs +++ b/src/Tests/Broadcast.Test/EventSourcing/TaskStoreTests.cs @@ -442,7 +442,8 @@ public void TaskStore_PropagateServer() { Id = "1", Name = "server", - Heartbeat = DateTime.Now + Heartbeat = DateTime.Now, + Expiration = DateTime.Now.AddMilliseconds(1000) }; var store = new TaskStore(); diff --git a/src/Tests/Broadcast.Test/Processing/TaskProcessorTests.cs b/src/Tests/Broadcast.Test/Processing/TaskProcessorTests.cs index 27b1fb3..35806dd 100644 --- a/src/Tests/Broadcast.Test/Processing/TaskProcessorTests.cs +++ b/src/Tests/Broadcast.Test/Processing/TaskProcessorTests.cs @@ -17,7 +17,7 @@ public class TaskProcessorTests public void TaskProcessor_ctor() { var store = new Mock(); - Assert.DoesNotThrow(() => new TaskProcessor(store.Object, new Options())); + Assert.DoesNotThrow(() => new TaskProcessor(store.Object, new ProcessorOptions())); } [Test] @@ -30,14 +30,14 @@ public void TaskProcessor_ctor_Null_Options() [Test] public void TaskProcessor_ctor_Null_Store() { - Assert.Throws(() => new TaskProcessor(null, new Options())); + Assert.Throws(() => new TaskProcessor(null, new ProcessorOptions())); } [Test] public void TaskProcessor_Queue() { var store = new Mock(); - var processor = new TaskProcessor(store.Object, new Options()); + var processor = new TaskProcessor(store.Object, new ProcessorOptions()); Assert.IsNotNull(processor.Queue); } @@ -46,7 +46,7 @@ public void TaskProcessor_Queue() public void TaskProcessor_Process_SetState() { var store = new Mock(); - var processor = new TaskProcessor(store.Object, new Options()); + var processor = new TaskProcessor(store.Object, new ProcessorOptions()); var task = TaskFactory.CreateTask(() => Console.WriteLine("TaskProcessor")); processor.Process(task); @@ -58,7 +58,7 @@ public void TaskProcessor_Process_SetState() public void TaskProcessor_Process_SetState_Storage() { var store = new Mock(); - var processor = new TaskProcessor(store.Object, new Options()); + var processor = new TaskProcessor(store.Object, new ProcessorOptions()); processor.Process(TaskFactory.CreateTask(() => Console.WriteLine("TaskProcessor"))); @@ -69,7 +69,7 @@ public void TaskProcessor_Process_SetState_Storage() public void TaskProcessor_Process_ValidateState_Queued() { var store = new Mock(); - var processor = new TaskProcessor(store.Object, new Options()); + var processor = new TaskProcessor(store.Object, new ProcessorOptions()); var task = TaskFactory.CreateTask(() => Console.WriteLine("TaskProcessor")); processor.Process(task); diff --git a/src/Tests/Broadcast.Test/Server/BroadcasterHeartbeatDispatcherTests.cs b/src/Tests/Broadcast.Test/Server/BroadcasterHeartbeatDispatcherTests.cs index 68efb51..ba79ae8 100644 --- a/src/Tests/Broadcast.Test/Server/BroadcasterHeartbeatDispatcherTests.cs +++ b/src/Tests/Broadcast.Test/Server/BroadcasterHeartbeatDispatcherTests.cs @@ -16,13 +16,13 @@ public class BroadcasterHeartbeatDispatcherTests public void BroadcasterHeartbeatDispatcher_ctor() { var storage = new Mock(); - Assert.DoesNotThrow(() => new BroadcasterHeartbeatDispatcher(storage.Object, new Options())); + Assert.DoesNotThrow(() => new BroadcasterHeartbeatDispatcher(storage.Object, new ProcessorOptions())); } [Test] public void BroadcasterHeartbeatDispatcher_ctor_Null_Storage() { - Assert.Throws(() => new BroadcasterHeartbeatDispatcher(null, new Options())); + Assert.Throws(() => new BroadcasterHeartbeatDispatcher(null, new ProcessorOptions())); } [Test] @@ -35,7 +35,7 @@ public void BroadcasterHeartbeatDispatcher_ctor_Null_Options() [Test] public void BroadcasterHeartbeatDispatcher_Execute() { - var options = new Options + var options = new ProcessorOptions { ServerName = "BroadcasterHeartbeatDispatcher", HeartbeatInterval = 1 @@ -56,7 +56,7 @@ public void BroadcasterHeartbeatDispatcher_Execute() [Test] public void BroadcasterHeartbeatDispatcher_Execute_SetStorage() { - var options = new Options + var options = new ProcessorOptions { ServerName = "BroadcasterHeartbeatDispatcher", HeartbeatInterval = 1 @@ -79,7 +79,7 @@ public void BroadcasterHeartbeatDispatcher_Execute_SetStorage() [Test] public void BroadcasterHeartbeatDispatcher_Execute_PropagateEvent() { - var options = new Options + var options = new ProcessorOptions { ServerName = "BroadcasterHeartbeatDispatcher", HeartbeatInterval = 1 diff --git a/src/Tests/Broadcast.Test/Setup/ServerSetupExtensionsTests.cs b/src/Tests/Broadcast.Test/Setup/ServerSetupExtensionsTests.cs index 2aeebfd..cc91d16 100644 --- a/src/Tests/Broadcast.Test/Setup/ServerSetupExtensionsTests.cs +++ b/src/Tests/Broadcast.Test/Setup/ServerSetupExtensionsTests.cs @@ -33,21 +33,21 @@ public void ServerSetup_UseTaskStore_ContainsKey() [Test] public void ServerSetup_UseOptions() { - var options = new Options(); + var options = new ProcessorOptions(); var setup = new ServerSetup(); setup.UseOptions(options); - Assert.AreSame(options, setup.Context[nameof(Options)]); + Assert.AreSame(options, setup.Context[nameof(ProcessorOptions)]); } [Test] public void ServerSetup_UseOptions_ContainsKey() { var setup = new ServerSetup(); - setup.UseOptions(new Options()); + setup.UseOptions(new ProcessorOptions()); - Assert.IsTrue(setup.Context.ContainsKey(nameof(Options))); + Assert.IsTrue(setup.Context.ContainsKey(nameof(ProcessorOptions))); } [Test] From 03dec38170247fd03be256c3e77d6fee407c6b6c Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sun, 5 Dec 2021 21:35:24 +0100 Subject: [PATCH 78/92] Count all threads used for processing --- src/Broadcast/Processing/IThreadList.cs | 39 ++++++++ src/Broadcast/Processing/ThreadCounter.cs | 56 +++++++++++ .../Processing/ThreadHandlerEventArgs.cs | 20 ++++ src/Broadcast/Processing/ThreadList.cs | 43 +++++++-- .../Behaviour/ThreadListTests.cs | 93 +++++++++++++++++++ .../Processing/ThreadCounterTests.cs | 30 ++++++ .../Processing/ThreadListTests.cs | 62 +++++++++++++ 7 files changed, 337 insertions(+), 6 deletions(-) create mode 100644 src/Broadcast/Processing/IThreadList.cs create mode 100644 src/Broadcast/Processing/ThreadCounter.cs create mode 100644 src/Broadcast/Processing/ThreadHandlerEventArgs.cs create mode 100644 src/Tests/Broadcast.Integration.Test/Behaviour/ThreadListTests.cs create mode 100644 src/Tests/Broadcast.Test/Processing/ThreadCounterTests.cs create mode 100644 src/Tests/Broadcast.Test/Processing/ThreadListTests.cs diff --git a/src/Broadcast/Processing/IThreadList.cs b/src/Broadcast/Processing/IThreadList.cs new file mode 100644 index 0000000..1b9d2be --- /dev/null +++ b/src/Broadcast/Processing/IThreadList.cs @@ -0,0 +1,39 @@ +using System; +using System.Threading.Tasks; + +namespace Broadcast.Processing +{ + /// + /// A list of running threads + /// + public interface IThreadList + { + /// + /// The Eventhandler used to notify when a thread is created or removed + /// + event EventHandler ThreadCountHandler; + + /// + /// Add a task to the threadlist + /// + /// + void Add(Task task); + + /// + /// Remove a task from the threadlist + /// + /// + void Remove(Task task); + + /// + /// Wait for all threads to end + /// + void WaitAll(); + + /// + /// Gets the count of threads in the list + /// + /// + int Count(); + } +} diff --git a/src/Broadcast/Processing/ThreadCounter.cs b/src/Broadcast/Processing/ThreadCounter.cs new file mode 100644 index 0000000..76f78ef --- /dev/null +++ b/src/Broadcast/Processing/ThreadCounter.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Broadcast.Processing +{ + /// + /// Counts all threads that are allocated by the + /// + public class ThreadCounter : IDisposable + { + private static readonly Dictionary _counters = new Dictionary(); + + /// + /// Creates a new ThreadCounter and registers all events to + /// + /// + public ThreadCounter(IThreadList threads) + { + threads.ThreadCountHandler += Threads_ThreadCountHandler; + } + + private void Threads_ThreadCountHandler(object sender, ThreadHandlerEventArgs e) + { + lock (_counters) + { + _counters[e.Name] = e.Count; + } + } + + /// + /// Dispose the ThreadCounter + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + } + + /// + /// Get the sum over all Threads registered to + /// + /// + public static int GetTotalThreadCount() + { + lock (_counters) + { + return _counters.Values.Sum(); + } + } + } +} diff --git a/src/Broadcast/Processing/ThreadHandlerEventArgs.cs b/src/Broadcast/Processing/ThreadHandlerEventArgs.cs new file mode 100644 index 0000000..aef2c96 --- /dev/null +++ b/src/Broadcast/Processing/ThreadHandlerEventArgs.cs @@ -0,0 +1,20 @@ +using System; + +namespace Broadcast.Processing +{ + /// + /// EventArgs for the ThreadCounter + /// + public class ThreadHandlerEventArgs : EventArgs + { + /// + /// Name of the + /// + public string Name { get; set; } + + /// + /// Count of threads contained in the + /// + public int Count { get; set; } + } +} diff --git a/src/Broadcast/Processing/ThreadList.cs b/src/Broadcast/Processing/ThreadList.cs index 78444df..1cb03e0 100644 --- a/src/Broadcast/Processing/ThreadList.cs +++ b/src/Broadcast/Processing/ThreadList.cs @@ -1,18 +1,36 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Threading; using System.Threading.Tasks; namespace Broadcast.Processing { - /// + /// /// A list of running threads /// - public class ThreadList - { + public class ThreadList : IThreadList + { + private readonly List _taskList = new List(); + private readonly string _name; + private EventHandler _threadCountHandler; + private readonly ThreadCounter _threadCounter; - private readonly List _taskList = new List(); + public ThreadList() + { + _name = Guid.NewGuid().ToString(); + _threadCounter = new ThreadCounter(this); + } + + /// + /// The Eventhandler used to notify when a thread is created or removed + /// + public event EventHandler ThreadCountHandler + { + add => _threadCountHandler += value; + remove => _threadCountHandler -= value; + } /// /// Add a task to the threadlist @@ -23,6 +41,8 @@ public void Add(Task task) lock(_taskList) { _taskList.Add(task); + _threadCountHandler?.Invoke(this, new ThreadHandlerEventArgs { Name = _name, Count = _taskList.Count }); + task.ContinueWith(t => { // make sure the thread is completed @@ -43,9 +63,16 @@ public void Remove(Task task) if (_taskList.Contains(task)) { Trace.WriteLine($"Remove Thread with state: {task.Status}"); + if (task.Status == TaskStatus.Running) + { + task.Wait(); + } + task.Dispose(); _taskList.Remove(task); - } + } + + _threadCountHandler?.Invoke(this, new ThreadHandlerEventArgs { Name = _name, Count = _taskList.Count }); } } @@ -72,7 +99,11 @@ private Task[] GetTaskArray() } } - private int Count() + /// + /// Gets the count of threads in the list + /// + /// + public int Count() { lock (_taskList) { diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/ThreadListTests.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/ThreadListTests.cs new file mode 100644 index 0000000..4239476 --- /dev/null +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/ThreadListTests.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using BDTest.Attributes; +using BDTest.Test; +using Broadcast.Processing; +using FluentAssertions; +using NUnit.Framework; + +namespace Broadcast.Integration.Test.Behaviour +{ + public class ThreadListTests : BDTestBase + { + [TearDown] + public void Teardown() + { + Task.Delay(700).Wait(); + } + + [Test] + [ScenarioText("Create a ThreadList to check the amount of threads")] + public void CountSingleThreadInThreadList() + { + WithContext(context => + Given(() => CreateThreadList(context)) + .When(() => StartSingleThread(context)) + .Then(() => ThreadCounterShowsCounts(1)) + .BDTest() + ); + } + + [Test] + [ScenarioText("Create a ThreadList to check the amount of threads when multiple are added")] + public void CountThreadsInThreadList() + { + WithContext(context => + Given(() => CreateThreadList(context)) + .When(() => StartThreeThreads(context)) + .Then(() => ThreadCounterShowsCounts(3)) + .BDTest() + ); + } + + [Test] + [ScenarioText("Create multiple ThreadLists to check the amount of threads are cumulated")] + public void CountThreadsInMultipleThreadLists() + { + WithContext(context => + Given(() => CreateThreadList(context)) + .And(() => CreateThreadList(context)) + .And(() => CreateThreadList(context)) + .When(() => StartThreeThreadsOnThreeLists(context)) + .Then(() => ThreadCounterShowsCounts(3)) + .BDTest() + ); + } + + public void CreateThreadList(ThreadListContext context) + { + context.ThreadLists.Add(new ThreadList()); + } + + private void StartSingleThread(ThreadListContext context) + { + context.ThreadLists[0].Add(Task.Factory.StartNew(() => { Task.Delay(500).Wait(); })); + } + + private void StartThreeThreads(ThreadListContext context) + { + context.ThreadLists[0].Add(Task.Factory.StartNew(() => { Task.Delay(500).Wait(); })); + context.ThreadLists[0].Add(Task.Factory.StartNew(() => { Task.Delay(500).Wait(); })); + context.ThreadLists[0].Add(Task.Factory.StartNew(() => { Task.Delay(500).Wait(); })); + } + + private void StartThreeThreadsOnThreeLists(ThreadListContext context) + { + context.ThreadLists[0].Add(Task.Factory.StartNew(() => { Task.Delay(500).Wait(); })); + context.ThreadLists[1].Add(Task.Factory.StartNew(() => { Task.Delay(500).Wait(); })); + context.ThreadLists[2].Add(Task.Factory.StartNew(() => { Task.Delay(500).Wait(); })); + } + + private void ThreadCounterShowsCounts(int count) + { + ThreadCounter.GetTotalThreadCount().Should().Be(count); + } + } + + public class ThreadListContext + { + public List ThreadLists { get; } = new List(); + } +} diff --git a/src/Tests/Broadcast.Test/Processing/ThreadCounterTests.cs b/src/Tests/Broadcast.Test/Processing/ThreadCounterTests.cs new file mode 100644 index 0000000..b8a892b --- /dev/null +++ b/src/Tests/Broadcast.Test/Processing/ThreadCounterTests.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Broadcast.Processing; +using Moq; +using NUnit.Framework; + +namespace Broadcast.Test.Processing +{ + public class ThreadCounterTests + { + [Test] + public void ThreadCounter_ctor() + { + Assert.DoesNotThrow(() => new ThreadCounter(new Mock().Object)); + } + + [Test] + public void ThreadCounter_AddCount() + { + var threadList = new Mock(); + new ThreadCounter(threadList.Object); + + threadList.Raise(exp => exp.ThreadCountHandler += null, new ThreadHandlerEventArgs { Name = "test1", Count = 2 }); + threadList.Raise(exp => exp.ThreadCountHandler += null, new ThreadHandlerEventArgs { Name = "test2", Count = 2 }); + + Assert.AreEqual(4, ThreadCounter.GetTotalThreadCount()); + } + } +} diff --git a/src/Tests/Broadcast.Test/Processing/ThreadListTests.cs b/src/Tests/Broadcast.Test/Processing/ThreadListTests.cs new file mode 100644 index 0000000..d5f6fcb --- /dev/null +++ b/src/Tests/Broadcast.Test/Processing/ThreadListTests.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Broadcast.Processing; +using NUnit.Framework; + +namespace Broadcast.Test.Processing +{ + public class ThreadListTests + { + [Test] + public void ThreadList_ctor() + { + Assert.DoesNotThrow(() => new ThreadList()); + } + + [Test] + public void ThreadList_Add() + { + var list = new ThreadList(); + list.Add(Task.Factory.StartNew(() => { Task.Delay(500).Wait(); })); + + Assert.AreEqual(1, list.Count()); + } + + [Test] + public void ThreadList_Add_RemoveOnFinish() + { + var list = new ThreadList(); + list.Add(Task.Factory.StartNew(() => { })); + + Task.Delay(10).Wait(); + + Assert.AreEqual(0, list.Count()); + } + + [Test] + public void ThreadList_Remove() + { + var list = new ThreadList(); + + var task = Task.Factory.StartNew(() => { Task.Delay(50).Wait(); }); + list.Add(task); + list.Remove(task); + + Assert.AreEqual(0, list.Count()); + } + + [Test] + public void ThreadList_WaitAll() + { + var list = new ThreadList(); + + var task = Task.Factory.StartNew(() => { Task.Delay(50).Wait(); }); + list.Add(task); + list.WaitAll(); + + Assert.AreEqual(0, list.Count()); + } + } +} From f2c8162f89296e939cb87d8534cb1569d36b087f Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Sun, 5 Dec 2021 22:16:02 +0100 Subject: [PATCH 79/92] Show Threadcount in the metrics --- .../Assets/js/broadcast-dashboard.js | 6 +-- .../Assets/views/dashboard.html | 16 +++++-- .../Dispatchers/DashboardMetricsDispatcher.cs | 42 +++++++++++++++++++ src/Broadcast.Dashboard/Routes.cs | 1 + src/Broadcast/Monitoring/Metric.cs | 19 +++++++++ src/Broadcast/Monitoring/MonitoringService.cs | 19 ++++++++- 6 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 src/Broadcast.Dashboard/Dispatchers/DashboardMetricsDispatcher.cs create mode 100644 src/Broadcast/Monitoring/Metric.cs diff --git a/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js b/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js index 503855f..937af38 100644 --- a/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js +++ b/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js @@ -5,9 +5,6 @@ export class BroadcastDashboard extends BroadcastBase { super(); this.config = config; - //setTimeout(() => { - // this.startPolling(config, (data) => this.updateDashboard(data, this)); - //}, 3000); this.startPolling(config, (data) => this.updateDashboard(data, this)); document.querySelector('#tasklist').addEventListener('click', @@ -55,6 +52,7 @@ export class BroadcastDashboard extends BroadcastBase { updateDashboard(data, dashboard) { // servers this.updateElement(document.querySelector('#broadcast-servers-count'), data.servers.length); + this.updateElement(document.querySelector('#broadcast-threads-count'), data.metrics[0].value); var serverList = document.querySelector('#serverlist'); data.servers.forEach(s => { var serverElem = serverList.querySelector(`#serverheartbeat_${s.id}`); @@ -345,7 +343,7 @@ export class BroadcastDashboard extends BroadcastBase { if (dashboardConfig === undefined) { dashboardConfig = { - pollUrl: "%(RouteBasePath)/dashboard/metrics", + pollUrl: "%(RouteBasePath)/dashboard/data", dashboardUrl: "%(RouteBasePath)/dashboard", pollInterval: 1000 }; diff --git a/src/Broadcast.Dashboard/Assets/views/dashboard.html b/src/Broadcast.Dashboard/Assets/views/dashboard.html index 9820100..266e602 100644 --- a/src/Broadcast.Dashboard/Assets/views/dashboard.html +++ b/src/Broadcast.Dashboard/Assets/views/dashboard.html @@ -26,12 +26,22 @@
+
+
+

Servers

+
+
+ + - + +
+
-

Servers

+

Open Threads

- + -
@@ -177,7 +187,7 @@

Title : var dashboardConfig = { - pollUrl: "%(RouteBasePath)/dashboard/metrics", + pollUrl: "%(RouteBasePath)/dashboard/data", dashboardUrl: "%(RouteBasePath)/dashboard", pollInterval: 1000 } diff --git a/src/Broadcast.Dashboard/Dispatchers/DashboardMetricsDispatcher.cs b/src/Broadcast.Dashboard/Dispatchers/DashboardMetricsDispatcher.cs new file mode 100644 index 0000000..970642d --- /dev/null +++ b/src/Broadcast.Dashboard/Dispatchers/DashboardMetricsDispatcher.cs @@ -0,0 +1,42 @@ +using System.Threading.Tasks; +using Broadcast.Monitoring; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Serialization; + +namespace Broadcast.Dashboard.Dispatchers +{ + /// + /// Dispatcher for metrics used in the console + /// + public class DashboardMetricsDispatcher : IDashboardDispatcher + { + /// + /// Execute the dispatcher + /// + /// + /// + public async Task Dispatch(IDashboardContext context) + { + var monitoring = new MonitoringService(context.TaskStore); + + var monitor = new + { + Metrics = monitoring.GetMetrics(), + Servers = monitoring.GetServers(), + Tasks = monitoring.GetAllTasks(), + RecurringTasks = monitoring.GetRecurringTasks() + }; + + var settings = new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver(), + Converters = new JsonConverter[] { new StringEnumConverter { NamingStrategy = new CamelCaseNamingStrategy() } } + }; + var serialized = JsonConvert.SerializeObject(monitor, settings); + + context.Response.ContentType = "application/json"; + await context.Response.WriteAsync(serialized); + } + } +} diff --git a/src/Broadcast.Dashboard/Routes.cs b/src/Broadcast.Dashboard/Routes.cs index cd5d965..5cc33ed 100644 --- a/src/Broadcast.Dashboard/Routes.cs +++ b/src/Broadcast.Dashboard/Routes.cs @@ -13,6 +13,7 @@ static Routes() RouteCollection = new RouteCollection(); RouteCollection.Add("/dashboard/metrics", new ConsoleMetricsDispatcher()); + RouteCollection.Add("/dashboard/data", new DashboardMetricsDispatcher()); RouteCollection.Add("/dashboard/data/task/(?.+)", new DashboardTaskDataDispatcher()); RouteCollection.Add("/dashboard/data/server/(?.+)", new DashboardServerDataDispatcher()); RouteCollection.Add("/dashboard/data/recurringtask/(?.+)", new DashboardRecurringTaskDataDispatcher()); diff --git a/src/Broadcast/Monitoring/Metric.cs b/src/Broadcast/Monitoring/Metric.cs new file mode 100644 index 0000000..7282415 --- /dev/null +++ b/src/Broadcast/Monitoring/Metric.cs @@ -0,0 +1,19 @@ + +namespace Broadcast.Monitoring +{ + /// + /// Metric object showing the state of a + /// + public class Metric + { + /// + /// Name of the Metric + /// + public string Name { get; set; } + + /// + /// Value of the metric + /// + public string Value { get; set; } + } +} diff --git a/src/Broadcast/Monitoring/MonitoringService.cs b/src/Broadcast/Monitoring/MonitoringService.cs index d062ab7..2bd49fa 100644 --- a/src/Broadcast/Monitoring/MonitoringService.cs +++ b/src/Broadcast/Monitoring/MonitoringService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Broadcast.Processing; using Broadcast.Server; using Broadcast.Storage; @@ -108,5 +109,21 @@ public IEnumerable GetRecurringTasks() return recurring; } - } + + /// + /// Get a list of that show the state of the application + /// + /// + public IEnumerable GetMetrics() + { + return new List + { + new Metric + { + Name = "Open Threads", + Value = ThreadCounter.GetTotalThreadCount().ToString() + } + }; + } + } } From 713baee9eeafb1b27c86844f0086428f2979feec Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Mon, 6 Dec 2021 21:13:29 +0100 Subject: [PATCH 80/92] Show no data when viewing a deleted task --- src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js b/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js index 937af38..a68e574 100644 --- a/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js +++ b/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js @@ -235,7 +235,14 @@ export class BroadcastDashboard extends BroadcastBase { return response.json(); }).then(function(response) { var rows = ''; - + if (response === null) { + response = { + groups: [], + title: 'task', + key: `No taskdata availiable for ${id}` + } + } + response.groups.forEach(g => { if (g.values.length > 0) { rows = rows + `

${g.title}

`; From 654d7cc12bb9027f0e3f2fa40b461a7a45398738 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Mon, 6 Dec 2021 21:31:16 +0100 Subject: [PATCH 81/92] Cleanup sample --- .../Controllers/DashboardApiController.cs | 34 --- .../Controllers/DashboardController.cs | 137 --------- .../Controllers/StorageController.cs | 149 ---------- .../Views/Dashboard/EnqueuedTasks.cshtml | 36 --- .../Views/Dashboard/FailedTasks.cshtml | 36 --- .../Views/Dashboard/Index.cshtml | 166 ----------- .../Views/Dashboard/ProcessedTasks.cshtml | 42 --- .../Views/Dashboard/RecurringTasks.cshtml | 35 --- .../Views/Dashboard/Servers.cshtml | 30 -- .../Views/Dashboard/_Layout.cshtml | 57 ---- .../Views/Shared/_Layout.cshtml | 11 - .../Views/Shared/_LayoutBasic.cshtml | 5 - .../Views/Storage/Index.cshtml | 56 ---- .../Views/Storage/Partials/_StorageKey.cshtml | 36 --- .../wwwroot/js/broadcast-base.js | 49 --- .../wwwroot/js/broadcast-dashboard.js | 280 ------------------ .../wwwroot/js/broadcast-storage.js | 35 --- 17 files changed, 1194 deletions(-) delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/Controllers/DashboardApiController.cs delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/Controllers/DashboardController.cs delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/Controllers/StorageController.cs delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/EnqueuedTasks.cshtml delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/FailedTasks.cshtml delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/Index.cshtml delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/ProcessedTasks.cshtml delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/RecurringTasks.cshtml delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/Servers.cshtml delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/_Layout.cshtml delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/Views/Storage/Index.cshtml delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/Views/Storage/Partials/_StorageKey.cshtml delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-base.js delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-dashboard.js delete mode 100644 src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-storage.js diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Controllers/DashboardApiController.cs b/src/Tests/Broadcast.AspNetCore.TestApp/Controllers/DashboardApiController.cs deleted file mode 100644 index ae8b993..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Controllers/DashboardApiController.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Broadcast.AspNetCore.Test.Models; -using Broadcast.Monitoring; -using Microsoft.AspNetCore.Mvc; - -namespace Broadcast.AspNetCore.Test.Controllers -{ - public class DashboardApiController : ControllerBase - { - private readonly ITaskStore _store; - - public DashboardApiController(ITaskStore store) - { - _store = store; - } - - [HttpGet] - [Route("/dashboard/metrics")] - public IActionResult Get() - { - var monitoring = new MonitoringService(_store); - - var model = new DashboardModel - { - Monitor = new MonitorModel - { - Servers = monitoring.GetServers(), - Tasks = monitoring.GetAllTasks(), - RecurringTasks = monitoring.GetRecurringTasks() - } - }; - return Ok(model); - } - } -} diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Controllers/DashboardController.cs b/src/Tests/Broadcast.AspNetCore.TestApp/Controllers/DashboardController.cs deleted file mode 100644 index b0ad3d2..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Controllers/DashboardController.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; -using Broadcast.AspNetCore.Test.Models; -using Broadcast.EventSourcing; -using Broadcast.Monitoring; -using Broadcast.Server; -using Broadcast.Storage; -using Microsoft.AspNetCore.Mvc; - -namespace Broadcast.AspNetCore.Test.Controllers -{ - public class DashboardController : Controller - { - private readonly ITaskStore _store; - - public DashboardController(ITaskStore store) - { - _store = store; - } - - public IActionResult Index() - { - var monitoring = new MonitoringService(_store); - - var model = new DashboardModel - { - Monitor = new MonitorModel - { - Servers = monitoring.GetServers(), - Tasks = monitoring.GetAllTasks(), - RecurringTasks = monitoring.GetRecurringTasks() - } - }; - - return View(model); - } - - public IActionResult Servers() - { - var monitoring = new MonitoringService(_store); - - var model = new DashboardModel - { - Monitor = new MonitorModel - { - Servers = monitoring.GetServers(), - Tasks = monitoring.GetAllTasks(), - RecurringTasks = monitoring.GetRecurringTasks() - }, - Action = "Servers" - }; - - return View(model); - } - - public IActionResult RecurringTasks() - { - var monitoring = new MonitoringService(_store); - - var model = new DashboardModel - { - Monitor = new MonitorModel - { - Servers = monitoring.GetServers(), - Tasks = monitoring.GetAllTasks(), - RecurringTasks = monitoring.GetRecurringTasks() - }, - Action = "RecurringTasks" - }; - - return View(model); - } - - public IActionResult EnqueuedTasks() - { - var monitoring = new MonitoringService(_store); - - var model = new DashboardModel - { - Monitor = new MonitorModel - { - Servers = monitoring.GetServers(), - Tasks = monitoring.GetAllTasks(), - RecurringTasks = monitoring.GetRecurringTasks() - }, - Action = "EnqueuedTasks" - }; - - return View(model); - } - - public IActionResult ProcessedTasks() - { - var monitoring = new MonitoringService(_store); - - var model = new DashboardModel - { - Monitor = new MonitorModel - { - Servers = monitoring.GetServers(), - Tasks = monitoring.GetAllTasks(), - RecurringTasks = monitoring.GetRecurringTasks() - }, - Action = "ProcessedTasks" - }; - - return View(model); - } - - public IActionResult FailedTasks() - { - var monitoring = new MonitoringService(_store); - - var model = new DashboardModel - { - Monitor = new MonitorModel - { - Servers = monitoring.GetServers(), - Tasks = monitoring.GetAllTasks(), - RecurringTasks = monitoring.GetRecurringTasks() - }, - Action = "FailedTasks" - }; - - return View(model); - } - - [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] - public IActionResult Error() - { - return View(new ErrorViewModel {RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier}); - } - } -} diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Controllers/StorageController.cs b/src/Tests/Broadcast.AspNetCore.TestApp/Controllers/StorageController.cs deleted file mode 100644 index 2a4b224..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Controllers/StorageController.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.Json; -using System.Threading.Tasks; -using Broadcast.EventSourcing; -using Broadcast.Server; -using Broadcast.Storage; -using Broadcast.Storage.Inmemory; -using Microsoft.AspNetCore.Mvc; - -namespace Broadcast.AspNetCore.Test.Controllers -{ - public class StorageController : Controller - { - private readonly ITaskStore _store; - - public StorageController(ITaskStore store) - { - _store = store; - } - - public IActionResult Index() - { - var model = new StorageModel - { - - }; - - _store.Storage(s => - { - model.Items = new List(); - - model.Items.Add(GetData("Servers", "server:", s)); - var tasks = GetData("Tasks", "task:", s); - foreach (var task in tasks.Items) - { - var id = task.Values.FirstOrDefault(t => t.Key == "Id"); - if (id == null) - { - continue; - } - - var data = s.Get(new StorageKey($"tasks:values:{id.Value}")); - if (data == null) - { - continue; - } - - var values = task.Values.ToList(); - values.AddRange(data.Select(d => new StorageProperty(d.Key, d.Value))); - task.Values = values; - } - - model.Items.Add(tasks); - model.Items.Add(GetData("Recurring tasks", "tasks:recurring:", s)); - - var storageType = new StorageType - { - Key = "Processing" - }; - storageType.Items.Add(GetList("tasks:dequeued", s)); - storageType.Items.Add(GetList("tasks:enqueued", s)); - var queues = s.GetKeys(new StorageKey("queue:")); - foreach (var queue in queues) - { - storageType.Items.Add(GetList(queue, s)); - } - - model.Items.Add(storageType); - }); - - return View(model); - } - - private StorageType GetData(string type, string storeKey, IStorage store) - { - var storageType = new StorageType - { - Key = type - }; - - foreach (var key in store.GetKeys(new Storage.StorageKey(storeKey)).ToList()) - { - var data = store.Get(new StorageKey(key)); - - var item = new StorageItem - { - Key = key, - Values = data.Select(d => new StorageProperty(d.Key, d.Value)) - }; - - storageType.Items.Add(item); - } - - return storageType; - } - - public StorageItem GetList(string storeKey, IStorage store) - { - var data = store.GetList(new StorageKey(storeKey)); - - var item = new StorageItem - { - Key = storeKey, - Values = data.Select(d => new StorageProperty("", d)) - }; - - return item; - } - } - - public class StorageModel - { - public List Items { get; set; } - } - - public class StorageType - { - public string Key{ get; set; } - - public List Items { get; set; } = new List(); - } - - public class StorageItem - { - public string Key { get; set; } - - public IEnumerable Values { get; set; } - } - - public class StorageProperty - { - public StorageProperty(string key, object value) - : this(key, value?.ToString()) - { - } - - public StorageProperty(string key, string value) - { - Key = key; - Value = value; - } - - public string Key { get; set; } - - public string Value { get; set; } - } -} diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/EnqueuedTasks.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/EnqueuedTasks.cshtml deleted file mode 100644 index c6f1d71..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/EnqueuedTasks.cshtml +++ /dev/null @@ -1,36 +0,0 @@ -@using Broadcast.EventSourcing -@model DashboardModel - -@{ - ViewData["Title"] = "Enqueued Tasks"; - Layout = "_Layout"; -} - -
-
- - - - - - - - - - - - @foreach (var task in Model.Monitor.Tasks.Where(t => t.State != TaskState.Processed && t.State != TaskState.Faulted)) - { - - - - - - - - } - -
IdNameStateIsRecurringInterval
@task.Id@task.Name@task.State@task.IsRecurring@task.Time
-
-
- diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/FailedTasks.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/FailedTasks.cshtml deleted file mode 100644 index bdf73f2..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/FailedTasks.cshtml +++ /dev/null @@ -1,36 +0,0 @@ -@using Broadcast.EventSourcing -@model DashboardModel - -@{ - ViewData["Title"] = "Failed Tasks"; - Layout = "_Layout"; -} - -
-
- - - - - - - - - - - - @foreach (var task in Model.Monitor.Tasks.Where(t => t.State == TaskState.Faulted)) - { - - - - - - - - } - -
IdNameStateIsRecurringInterval
@task.Id@task.Name@task.State@task.IsRecurring@task.Time
-
-
- diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/Index.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/Index.cshtml deleted file mode 100644 index cc0ab5f..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/Index.cshtml +++ /dev/null @@ -1,166 +0,0 @@ -@using Broadcast.EventSourcing -@model DashboardModel - -@{ - ViewData["Title"] = "Custom Dashboard"; - Layout = "_Layout"; -} - -
-
-
-
-
-

Servers

-
-
- - @Model.Monitor.Servers.Count() - -
-
-
-
-

Recurring Tasks

-
-
- - @Model.Monitor.RecurringTasks.Count() - -
-
-
-
-

Tasks total

-
-
- - @Model.Monitor.RecurringTasks.Count() - -
-
-
-
-

Enqueued Tasks

-
-
- - @Model.Monitor.Tasks.Count(t => t.State != TaskState.Processed && t.State != TaskState.Faulted) - -
-
-
-
-

Processed Tasks

-
-
- - @Model.Monitor.Tasks.Count(t => t.State == TaskState.Processed) - -
-
-
-
-

Failed Tasks

-
-
- - @Model.Monitor.Tasks.Count(t => t.State == TaskState.Faulted) - -
-
-
-
-
-
-
-

Servers

-
-
- - - - - - - - - @foreach (var server in Model.Monitor.Servers) - { - - - - - } - -
NameHeartbeat
@server.Name:@server.Id @server.Heartbeat.ToString("yyyy-MM-dd HH:mm:ss")
-
-
-
-
-

Recurring Tasks

-
-
- - - - - - - - - - - @foreach (var task in Model.Monitor.RecurringTasks) - { - var name = task.Name.Replace(".", "_"); - - - - - - - } - -
NameReferenced TaskIdNextExecutionInterval
@task.Name@task.ReferenceId@task.NextExecution.ToString("yyyy-MM-dd HH:mm:ss")@(task.Interval != null ? TimeSpan.FromMilliseconds(task.Interval.Value).ToString("hh\\:mm\\:ss\\.fff") : string.Empty)
-
-
-
-
-

Tasks

-
-
- - - - - - - - - - - - - - - @foreach (var task in Model.Monitor.Tasks) - { - - - - - - - - - - - } - -
IdNameStateIsRecurringIntervalServerStartedDuration
@task.Id@task.Name@task.State@task.IsRecurring@(task.Time != null ? TimeSpan.FromMilliseconds(task.Time.Value).ToString("hh\\:mm\\:ss\\.fff") : string.Empty)@task.Server@task.Start?.ToString("yyyy-MM-dd HH:mm:ss")@task.Duration
-
-
- - - diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/ProcessedTasks.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/ProcessedTasks.cshtml deleted file mode 100644 index 7debc1b..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/ProcessedTasks.cshtml +++ /dev/null @@ -1,42 +0,0 @@ -@using Broadcast.EventSourcing -@model DashboardModel - -@{ - ViewData["Title"] = "Processed Tasks"; - Layout = "_Layout"; -} - -
-
- - - - - - - - - - - - - - - @foreach (var task in Model.Monitor.Tasks.Where(t => t.State == TaskState.Processed)) - { - - - - - - - - - - - } - -
IdNameStateIsRecurringIntervalServerStartedDuration
@task.Id@task.Name@task.State@task.IsRecurring@(task.Time != null ? TimeSpan.FromMilliseconds(task.Time.Value).ToString("hh\\:mm\\:ss\\.fff") : string.Empty)@task.Server@task.Start?.ToString("yyyy-MM-dd HH:mm:ss")@task.Duration
-
-
- diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/RecurringTasks.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/RecurringTasks.cshtml deleted file mode 100644 index ccda51d..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/RecurringTasks.cshtml +++ /dev/null @@ -1,35 +0,0 @@ -@using Broadcast.EventSourcing -@model DashboardModel - -@{ - ViewData["Title"] = "Recurring Tasks"; - Layout = "_Layout"; -} - -
-
- - - - - - - - - - - @foreach (var task in Model.Monitor.RecurringTasks) - { - var name = task.Name.Replace(".", "_"); - - - - - - - } - -
NameReferenced TaskIdNextExecutionInterval
@task.Name@task.ReferenceId@task.NextExecution.ToString("yyyy-MM-dd HH:mm:ss")@(task.Interval != null ? TimeSpan.FromMilliseconds(task.Interval.Value).ToString("hh\\:mm\\:ss\\.fff") : string.Empty)
-
-
- diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/Servers.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/Servers.cshtml deleted file mode 100644 index 06bf8b6..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/Servers.cshtml +++ /dev/null @@ -1,30 +0,0 @@ -@using Broadcast.EventSourcing -@model DashboardModel - -@{ - ViewData["Title"] = "Servers"; - Layout = "_Layout"; -} - -
-
- - - - - - - - - @foreach (var server in Model.Monitor.Servers) - { - - - - - } - -
NameHeartbeat
@server.Name:@server.Id @server.Heartbeat.ToString("yyyy-MM-dd HH:mm:ss")
-
-
- diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/_Layout.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/_Layout.cshtml deleted file mode 100644 index bc9f76a..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Dashboard/_Layout.cshtml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - @ViewData["Title"] - Broadcast.AspNetCore.Test - - @await RenderSectionAsync("Styles", false) - - -
-
-
- @*@ViewData["Title"]*@ - Broadcast -
-
-
- @RenderBody() -
-
-
- -
-
-
-
-
- @*Add the name of the task here (key)*@ -
-

Title : Key

-
-
-
- -
-
-
-
- -
- - @await RenderSectionAsync("Scripts", required: false) - - - - - - diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/_Layout.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/_Layout.cshtml index 14b7424..5fe3d88 100644 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/_Layout.cshtml +++ b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/_Layout.cshtml @@ -23,21 +23,12 @@

@@ -54,8 +45,6 @@ © @DateTime.Now.Year - Broadcast
- @**@ - @**@ @await RenderSectionAsync("Scripts", required: false) diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/_LayoutBasic.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/_LayoutBasic.cshtml index f5656a5..a3e8bdb 100644 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/_LayoutBasic.cshtml +++ b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Shared/_LayoutBasic.cshtml @@ -4,8 +4,6 @@ @ViewData["Title"] - Broadcast.AspNetCore.Test - @**@ - @**@ @await RenderSectionAsync("Styles", false) @@ -13,9 +11,6 @@
@RenderBody()
- @**@ - @**@ - @**@ @await RenderSectionAsync("Scripts", required: false) diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Storage/Index.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Storage/Index.cshtml deleted file mode 100644 index a451ce4..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Storage/Index.cshtml +++ /dev/null @@ -1,56 +0,0 @@ -@model Broadcast.AspNetCore.Test.Controllers.StorageModel - -@{ - ViewData["Title"] = "Custom Dashboard"; -} - -@section styles{ - -} - -
-
-

Storage

-
-
- @foreach (var item in Model.Items) - { -
-
-
- -
-
- @item.Key -
-
-
- -
-
- } -
-
-
-
- -
-
-
- -
- -@section scripts{ - - - -} \ No newline at end of file diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Storage/Partials/_StorageKey.cshtml b/src/Tests/Broadcast.AspNetCore.TestApp/Views/Storage/Partials/_StorageKey.cshtml deleted file mode 100644 index 66067aa..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/Views/Storage/Partials/_StorageKey.cshtml +++ /dev/null @@ -1,36 +0,0 @@ -@model Broadcast.AspNetCore.Test.Controllers.StorageType - -@{ - ViewData["Title"] = "Custom Dashboard"; -} - - -@foreach (var item in Model.Items) -{ -
-
-
-
- @item.Key -
-
- @foreach (var property in item.Values) - { - @if (string.IsNullOrEmpty(property.Key)) - { -
-
@property.Value
-
- } - else - { -
-
@property.Key
-
@property.Value
-
- } - } -
-
-
-} \ No newline at end of file diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-base.js b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-base.js deleted file mode 100644 index b346ad6..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-base.js +++ /dev/null @@ -1,49 +0,0 @@ - -export class BroadcastBase { - constructor() { - } - - poll(fn, interval) { - interval = interval || 1000; - - var checkCondition = function (resolve, reject) { - fn().then(function (result) { - setTimeout(checkCondition, interval, resolve, reject); - }); - }; - - return new Promise(checkCondition); - } - - startPolling(config, func) { - this.poll(function () { - var fn = function (resolve, reject) { - var url = config.pollUrl; - fetch(url, - { - method: "GET", - headers: { 'content-type': 'application/json; charset=utf-8' } - } - ).then(function (response) { - if (!response.ok) { - throw Error(response.statusText); - } - return response.json(); - }).then(function (response) { - func(response); - resolve(false); - }).catch(function (error) { - console.log(error); - reject(error); - }); - }; - return new Promise(fn); - }, - 1000) - .then(function () { - // Polling done, now do something else! - }).catch(function () { - // Polling timed out, handle the error! - }); - } -} \ No newline at end of file diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-dashboard.js b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-dashboard.js deleted file mode 100644 index 27644aa..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-dashboard.js +++ /dev/null @@ -1,280 +0,0 @@ - -export class BroadcastDashboard { - constructor(config) { - this.config = config; - setTimeout(() => { - this.startPolling(config, (data) => this.updateDashboard(data, this)); - }, 3000); - - var tasklist = document.querySelector('#tasklist'); - if (tasklist) { - tasklist.addEventListener('click', - e => { - var row = e.target.closest('tr'); - if (row) { - this.showTaskDetail(config, row.dataset.taskId); - } - }); - - document.querySelector('#broadcast-overlay-close-btn').addEventListener('click', - e => { - e.target.closest('#broadcast-data-overlay').style.display = 'none'; - }); - } - } - - poll(fn, interval) { - interval = interval || 1000; - - var checkCondition = function (resolve, reject) { - fn().then(function (result) { - setTimeout(checkCondition, interval, resolve, reject); - }); - }; - - return new Promise(checkCondition); - } - - startPolling(config, func) { - this.poll(function () { - var fn = function (resolve, reject) { - var url = config.pollUrl; - fetch(url, - { - method: "GET", - headers: { 'content-type': 'application/json; charset=utf-8' } - } - ).then(function (response) { - if (!response.ok) { - throw Error(response.statusText); - } - return response.json(); - }).then(function (response) { - func(response); - resolve(false); - }).catch(function (error) { - console.log(error); - //reject(error); - resolve(false); - }); - }; - return new Promise(fn); - }, - 1000) - .then(function () { - // Polling done, now do something else! - }).catch(function () { - // Polling timed out, handle the error! - }); - } - - updateDashboard(data, dashboard) { - // servers - this.updateElement(document.querySelector('#broadcast-servers-count'), data.monitor.servers.length); - var serverList = document.querySelector('#serverlist'); - if (serverList) { - data.monitor.servers.forEach(s => { - this.updateElement(serverList.querySelector(`#serverheartbeat_${s.id}`), this.formatDate(new Date(s.heartbeat))); - }); - } - - // recurring tasks - this.updateElement(document.querySelector('#broadcast-recurring-count'), data.monitor.recurringTasks.length); - var recurringlist = document.querySelector('#recurringlist'); - if (recurringlist) { - data.monitor.recurringTasks.forEach(t => { - var name = t.name.replace('.', '_'); - var taskRow = recurringlist.querySelector(`#recurring_${name}`); - - if (taskRow) { - this.updateElement(taskRow.querySelector(`#referenceid_${name}`), t.referenceId); - this.updateElement(taskRow.querySelector(`#nextexecution_${name}`), this.formatDate(new Date(t.nextExecution))); - } else { - // add new row - var row = recurringlist.querySelector('tbody').insertRow(0); - row.id = `recurring_${name}`; - row.classList.add('broadcast-table-row'); - - this.addCell(row, 0, null, t.name); - this.addCell(row, 1, `referenceid_${name}`, t.referenceId); - this.addCell(row, 2, null, this.formatDate(new Date(t.nextExecution))); - this.addCell(row, 3, null, this.millisecondsToTime(t.interval)); - } - }); - } - - // tasks - var tasklist = document.querySelector('#tasklist'); - this.updateElement(document.querySelector('#broadcast-tasks-count'), data.monitor.tasks.length); - var cnt = 0; - var processedCnt = 0; - var failedCnt = 0; - data.monitor.tasks.forEach(t => { - if (t.state !== 4 && t.state !== 5) { - cnt = cnt + 1; - }else if (t.state === 4) { - processedCnt = processedCnt + 1; - } else if (t.state === 5) { - failedCnt = failedCnt + 1; - } - - if (tasklist) { - var taskRow = document.querySelector(`#task_${t.id}`); - var state = t.state === 0 - ? 'New' - : t.state === 1 - ? 'Queued' - : t.state === 2 - ? 'Dequeued' - : t.state === 3 - ? 'Processing' - : t.state === 4 - ? 'Processed' - : t.state === 5 - ? 'Faulted' - : 'Unknown'; - - if (taskRow) { - var stateElem = taskRow.querySelector(`#state_${t.id}`); - if (stateElem.innerText !== state) { - this.updateElement(stateElem, state); - this.updateElement(taskRow.querySelector(`#server_${t.id}`), t.server); - this.updateElement(taskRow.querySelector(`#start_${t.id}`), t.start ? this.formatDate(new Date(t.start)) : ''); - this.updateElement(taskRow.querySelector(`#duration_${t.id}`), t.duration); - } - } else { - // add new row - if (!tasklist.classList.contains('processed') || t.state === 4) { - var row = tasklist.querySelector('tbody').insertRow(0); - row.id = `task_${t.id}`; - row.setAttribute('data-task-id', t.id); - row.classList.add('broadcast-table-row'); - - this.addCell(row, 0, null, t.id); - this.addCell(row, 1, null, t.name); - this.addCell(row, 2, `state_${t.id}`, state); - this.addCell(row, 3, null, t.isRecurring); - this.addCell(row, 4, null, this.millisecondsToTime(t.time)); - this.addCell(row, 5, `server_${t.id}`, t.server); - this.addCell(row, 6, `start_${t.id}`, t.start ? this.formatDate(new Date(t.start)) : ''); - this.addCell(row, 7, `duration_${t.id}`, t.duration); - } - } - } - }); - this.updateElement(document.querySelector('#broadcast-enqueued-count'), cnt); - this.updateElement(document.querySelector('#broadcast-processed-count'), processedCnt); - this.updateElement(document.querySelector('#broadcast-failed-count'), failedCnt); - } - - addCell(row, index, id, value) { - var cell = row.insertCell(index); - cell.innerText = value; - if (id !== null) { - cell.id = id; - } - } - - millisecondsToTime(s) { - - // Pad to 2 or 3 digits, default is 2 - function pad(n, z) { - z = z || 2; - return ('00' + n).slice(-z); - } - - var ms = s % 1000; - s = (s - ms) / 1000; - var secs = s % 60; - s = (s - secs) / 60; - var mins = s % 60; - var hrs = (s - mins) / 60; - - return `${pad(hrs)}:${pad(mins)}:${pad(secs)}.${pad(ms, 3)}`; - } - - formatDate(date) { - var d = date.getDate(); - var m = date.getMonth() + 1; - var y = date.getFullYear(); - var h = date.getHours(); - var mn = date.getMinutes(); - var s = date.getSeconds(); - return '' + y + '-' + (m <= 9 ? '0' + m : m) + '-' + (d <= 9 ? '0' + d : d) + ' ' + (h <= 9 ? '0' + h : h) + ':' + (mn <= 9 ? '0' + mn : mn) + ':' + (s <= 9 ? '0' + s : s); - } - - updateElement(elem, data) { - elem.innerText = data; - } - - showTaskDetail(config, id) { - fetch(`${config.dataUrl}/task/${id}`, - { - method: "GET", - headers: { 'content-type': 'application/json; charset=utf-8' } - } - ).then(function(response) { - if (!response.ok) { - throw Error(response.statusText); - } - return response.json(); - }).then(function(response) { - var rows = ''; - - response.groups.forEach(g => { - if (g.values.length > 0) { - rows = rows + `

${g.title}

`; - g.values.forEach(p => { - if (p.key === '') { - rows = rows + - `
-
${p.value}
-
`; - } else { - rows = rows + - `
-
${p.key}
-
${p.value}
-
`; - } - }); - } - }); - - //response.values.forEach(p => { - // if (p.key === '') { - // rows = rows + - // `
- //
${p.value}
- //
`; - // } else { - // rows = rows + - // `
- //
${p.key}
- //
${p.value}
- //
`; - // } - //}); - - var overlay = document.querySelector('#broadcast-data-overlay'); - overlay.querySelector('#broadcast-data-title').innerText = response.title; - overlay.querySelector('#broadcast-data-key').innerText = response.key; - - overlay.querySelector('#broadcast-data-table').innerHTML = rows; - - overlay.style.display = 'block'; - - }); - } -} - -if (dashboardConfig === undefined) { - dashboardConfig = { - pollUrl: "/dashboard/metrics", - //TODO: /broadcast/ has to be able to be appended as configuration - dataUrl: "/broadcast/dashboard/data", - pollInterval: 2000 - }; -} - -const dashboard = new BroadcastDashboard(dashboardConfig); \ No newline at end of file diff --git a/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-storage.js b/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-storage.js deleted file mode 100644 index e629ade..0000000 --- a/src/Tests/Broadcast.AspNetCore.TestApp/wwwroot/js/broadcast-storage.js +++ /dev/null @@ -1,35 +0,0 @@ -import { BroadcastBase } from './broadcast-base.js'; - -export class BroadcastStorage extends BroadcastBase { - constructor(config) { - super(); - - this.config = config; - this.registerHandlers(); - } - - registerHandlers() { - document.querySelector('.broadcast-storage').addEventListener('click', - e => { - if (e.target.closest('.broadcast-toggler-button')) { - let elem = e.target.closest('.broadcast-toggler-section'); - elem.classList.toggle('is-open'); - } - - //if (e.target.closest('[data-value]')) { - // var elem = document.querySelector('#broadcast-storage-content'); - // elem.innerHTML = e.target.getAttribute('data-value'); - //} - }); - } -} - -if (storageConfig === undefined) { - storageConfig = { - //TODO: /broadcast/ has to be able to be appended as configuration - pollUrl: "/broadcast/storage", - pollInterval: 2000 - }; -} - -const storage = new BroadcastStorage(storageConfig); \ No newline at end of file From bb976a6e7aed2a602cbfcd65add443fa0bb006f0 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Mon, 6 Dec 2021 21:32:22 +0100 Subject: [PATCH 82/92] Use var keyword --- src/Broadcast.Dashboard/Assets/js/broadcast-console.js | 2 +- src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js | 2 +- src/Broadcast.Dashboard/Assets/js/broadcast-storage.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Broadcast.Dashboard/Assets/js/broadcast-console.js b/src/Broadcast.Dashboard/Assets/js/broadcast-console.js index 8828108..7af04af 100644 --- a/src/Broadcast.Dashboard/Assets/js/broadcast-console.js +++ b/src/Broadcast.Dashboard/Assets/js/broadcast-console.js @@ -77,7 +77,7 @@ export class BroadcastConsole extends BroadcastBase { } if (consoleConfig === undefined) { - consoleConfig = { + var consoleConfig = { pollUrl: "%(RouteBasePath)/dashboard/metrics", pollInterval: 1000, position: "TopRight" diff --git a/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js b/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js index a68e574..531c269 100644 --- a/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js +++ b/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js @@ -349,7 +349,7 @@ export class BroadcastDashboard extends BroadcastBase { } if (dashboardConfig === undefined) { - dashboardConfig = { + var dashboardConfig = { pollUrl: "%(RouteBasePath)/dashboard/data", dashboardUrl: "%(RouteBasePath)/dashboard", pollInterval: 1000 diff --git a/src/Broadcast.Dashboard/Assets/js/broadcast-storage.js b/src/Broadcast.Dashboard/Assets/js/broadcast-storage.js index 90da4b8..a5d2df6 100644 --- a/src/Broadcast.Dashboard/Assets/js/broadcast-storage.js +++ b/src/Broadcast.Dashboard/Assets/js/broadcast-storage.js @@ -120,7 +120,7 @@ ${this.createStorageValues(values)} } if (storageConfig === undefined) { - storageConfig = { + var storageConfig = { pollUrl: "%(RouteBasePath)/storage/keys", pollInterval: 2000 }; From 940f10953d90f0ed2430e050f543d1c622bfb7a1 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Mon, 6 Dec 2021 21:55:01 +0100 Subject: [PATCH 83/92] Fix blocker issues from sonarcloud --- src/Broadcast/EventSourcing/StorageObserver.cs | 3 +++ .../Broadcast.Integration.Test/BroadcasterTests.cs | 10 ++++++++-- .../StorageTests.cs | 10 ++++++++-- .../Broadcast.Test/Storage/InmemoryStorageTests.cs | 12 +++++++++--- src/Tests/Broadcast.Test/Storage/ListItemTests.cs | 4 ++++ 5 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/Broadcast/EventSourcing/StorageObserver.cs b/src/Broadcast/EventSourcing/StorageObserver.cs index 949f7b0..a4ff1c9 100644 --- a/src/Broadcast/EventSourcing/StorageObserver.cs +++ b/src/Broadcast/EventSourcing/StorageObserver.cs @@ -2,6 +2,7 @@ using Broadcast.Server; using System; using System.Threading; +using System.Threading.Tasks; using Broadcast.Configuration; namespace Broadcast.EventSourcing @@ -55,7 +56,9 @@ private void StartScheduler(BackgroundServerProcess process, Op thread.Start(); } +#pragma warning disable S3168 // "async" methods should not return "void" private async void ExecuteScheduler(BackgroundServerProcess process, Options options, ThreadWait threadWait) +#pragma warning restore S3168 // "async" methods should not return "void" { // loop until the waithandle is disposed while (threadWait.IsOpen) diff --git a/src/Tests/Broadcast.Integration.Test/BroadcasterTests.cs b/src/Tests/Broadcast.Integration.Test/BroadcasterTests.cs index 966dc9b..cdf9b42 100644 --- a/src/Tests/Broadcast.Integration.Test/BroadcasterTests.cs +++ b/src/Tests/Broadcast.Integration.Test/BroadcasterTests.cs @@ -7,6 +7,7 @@ using System.Threading; using System; using System.Linq.Expressions; +using FluentAssertions; namespace Broadcast.Integration.Test { @@ -272,14 +273,19 @@ public void BroadcasterAsyncTestInLoopFail() public void Broadcaster_Schedule() { var broadcaster = new Broadcaster(new TaskStore()); - broadcaster.Schedule(() => Console.WriteLine("test"), TimeSpan.FromMinutes(1)); + var id = broadcaster.Schedule(() => Console.WriteLine("test"), TimeSpan.FromMinutes(1)); + + id.Should().NotBeNull(); } [Test] public void Broadcaster_Recurring() { - var broadcaster = new Broadcaster(new TaskStore()); + var store = new TaskStore(); + var broadcaster = new Broadcaster(store); broadcaster.Recurring(() => Console.WriteLine("test"), TimeSpan.FromMinutes(1)); + + store.Should().HaveCount(1); } [Test] diff --git a/src/Tests/Broadcast.Storage.Integration.Test/StorageTests.cs b/src/Tests/Broadcast.Storage.Integration.Test/StorageTests.cs index 21e7675..16d85f5 100644 --- a/src/Tests/Broadcast.Storage.Integration.Test/StorageTests.cs +++ b/src/Tests/Broadcast.Storage.Integration.Test/StorageTests.cs @@ -38,7 +38,9 @@ public void Storage_Set() { var storage = BuildStorage(); storage.Set(new StorageKey("storage", "set"), "value"); - } + + Assert.IsNotNull(storage.Get(new StorageKey("storage", "set"))); + } [Test] public void Storage_Set_Object() @@ -96,6 +98,8 @@ public void Storage_AddToList() { var storage = BuildStorage(); storage.AddToList(new StorageKey("storage", "addtolist"), "value"); + + Assert.AreEqual(1, storage.GetList(new StorageKey("storage", "addtolist")).Count()); } [Test] @@ -104,7 +108,9 @@ public void Storage_AddToList_Multiple() var storage = BuildStorage(); storage.AddToList(new StorageKey("storage", "addtolist_multy"), "one"); storage.AddToList(new StorageKey("storage", "addtolist_multy"), "two"); - } + + Assert.AreEqual(2, storage.GetList(new StorageKey("storage", "addtolist_multy")).Count()); + } [Test] public void Storage_Get() diff --git a/src/Tests/Broadcast.Test/Storage/InmemoryStorageTests.cs b/src/Tests/Broadcast.Test/Storage/InmemoryStorageTests.cs index 93dd4b1..ee81462 100644 --- a/src/Tests/Broadcast.Test/Storage/InmemoryStorageTests.cs +++ b/src/Tests/Broadcast.Test/Storage/InmemoryStorageTests.cs @@ -13,15 +13,17 @@ public class InmemoryStorageTests { [Test] public void InmemoryStorage_Ctor() - { - var storage = new InmemoryStorage(); - } + { + Assert.DoesNotThrow(() => new InmemoryStorage()); + } [Test] public void InmemoryStorage_Set() { var storage = new InmemoryStorage(); storage.Set(new StorageKey("storage", "key"), "value"); + + Assert.IsNotNull(storage.Get(new StorageKey("storage", "key"))); } [Test] @@ -80,6 +82,8 @@ public void InmemoryStorage_AddToList() { var storage = new InmemoryStorage(); storage.AddToList(new StorageKey("storage", "key"), "value"); + + Assert.AreEqual(1, storage.GetList(new StorageKey("storage", "key")).Count()); } [Test] @@ -88,6 +92,8 @@ public void InmemoryStorage_AddToList_Multiple() var storage = new InmemoryStorage(); storage.AddToList(new StorageKey("storage", "key"), "one"); storage.AddToList(new StorageKey("storage", "key"), "two"); + + Assert.AreEqual(2, storage.GetList(new StorageKey("storage", "key")).Count()); } [Test] diff --git a/src/Tests/Broadcast.Test/Storage/ListItemTests.cs b/src/Tests/Broadcast.Test/Storage/ListItemTests.cs index 76dd949..6717953 100644 --- a/src/Tests/Broadcast.Test/Storage/ListItemTests.cs +++ b/src/Tests/Broadcast.Test/Storage/ListItemTests.cs @@ -20,6 +20,8 @@ public void ListItem_SetValue() { var item = new ListItem(); item.SetValue("value"); + + Assert.That(item.Count, Is.EqualTo(1)); } [Test] @@ -37,6 +39,8 @@ public void ListItem_GetValue() { var item = new ListItem(); item.SetValue("value"); + + Assert.That(item.GetValue(), Is.EquivalentTo(new []{"value"})); } [Test] From 2247850940e0a1a61f581ee7675af86da6d812cc Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Mon, 6 Dec 2021 22:05:25 +0100 Subject: [PATCH 84/92] Removed unnecessary property for scheduler count --- src/Broadcast/Scheduling/Scheduler.cs | 13 --------- .../Broadcast.Console.TestApp/Program.cs | 28 ------------------- .../Scheduling/SchedulerTests.cs | 23 --------------- 3 files changed, 64 deletions(-) diff --git a/src/Broadcast/Scheduling/Scheduler.cs b/src/Broadcast/Scheduling/Scheduler.cs index 24026b8..3613368 100644 --- a/src/Broadcast/Scheduling/Scheduler.cs +++ b/src/Broadcast/Scheduling/Scheduler.cs @@ -14,8 +14,6 @@ namespace Broadcast.Scheduling ///
public class Scheduler : IScheduler { - private static int _schedulerCount; - private readonly ISchedulerContext _context; private readonly IScheduleQueue _scheduleQueue; private readonly IBackgroundServerProcess _backgroundProcess; @@ -42,17 +40,8 @@ public Scheduler(IScheduleQueue queue) _backgroundProcess = new BackgroundServerProcess(_context); _backgroundProcess.StartNew(new SchedulerBackgroundProcess(_scheduleQueue)); - - _schedulerCount++; - - _logger.Write($"Started new Scheduler. New SchedulerCount: {_schedulerCount}"); } - /// - /// Gets the total count of Schedulers that are alive - /// - public static int SchedulerCount => _schedulerCount; - /// /// Enqueues and schedules a new task /// @@ -96,8 +85,6 @@ protected virtual void Dispose(bool disposing) _context.ThreadWait.Dispose(); _backgroundProcess.WaitAll(); - _schedulerCount--; - _logger.Write($"Disposed Scheduler. New SchedulerCount: {_schedulerCount}"); } } } diff --git a/src/Tests/Broadcast.Console.TestApp/Program.cs b/src/Tests/Broadcast.Console.TestApp/Program.cs index d263492..729d2f0 100644 --- a/src/Tests/Broadcast.Console.TestApp/Program.cs +++ b/src/Tests/Broadcast.Console.TestApp/Program.cs @@ -33,11 +33,6 @@ static void Main(string[] args) format = "Test Background {0}"; break; - //case "async": - // broadcaster = new Broadcaster(ProcessorMode.Async); - // format = "Test Async {0}"; - // break; - case "exit": return; @@ -51,7 +46,6 @@ static void Main(string[] args) scheduler.Schedule(() => System.Console.WriteLine(" Scheduled message 5 sec"), TimeSpan.FromSeconds(5)); scheduler.Schedule(() => System.Console.WriteLine(" Scheduled message 3 sec"), TimeSpan.FromSeconds(3)); - System.Console.WriteLine($"Starting scheduler with {Scheduler.SchedulerCount} schedulers"); scheduler.Send(() => System.Console.WriteLine("Direct message")); System.Console.ReadLine(); @@ -64,42 +58,20 @@ static void Main(string[] args) scheduler.Recurring(() => System.Console.WriteLine(" Recurring Expression 5 sec"), TimeSpan.FromSeconds(5)); scheduler.Recurring(() => System.Console.WriteLine(" Recurring Expression 3 sec"), TimeSpan.FromSeconds(3)); - System.Console.WriteLine($"Starting recurring with {Scheduler.SchedulerCount} schedulers"); scheduler.Send(() => System.Console.WriteLine("Direct message")); System.Console.ReadLine(); } break; - // case "recurring2": - // using (var scheduler = new Broadcaster()) - // { - // Action exp1 = () => System.Console.WriteLine(" Recurring Action 5 sec"); - // Action exp2 = () => System.Console.WriteLine(" Recurring Action 3 sec"); - //scheduler.Recurring(exp1, TimeSpan.FromSeconds(5)); - //scheduler.Recurring(exp2, TimeSpan.FromSeconds(3)); - - //System.Console.WriteLine($"Starting recurring with {Scheduler.SchedulerCount} schedulers"); - - // System.Console.ReadLine(); - // } - - // break; - case "multy": using (var scheduler = new Broadcaster()) { scheduler.Recurring(() => System.Console.WriteLine(" Recurring outer 5 sec"), TimeSpan.FromSeconds(5)); - //scheduler.Recurring(() => System.Console.WriteLine(" Recurring outer 3 sec"), TimeSpan.FromSeconds(3)); - - System.Console.WriteLine($"Starting recurring with {Scheduler.SchedulerCount} schedulers"); scheduler.Send(() => System.Console.WriteLine("Direct message")); using (var scheduler2 = new Broadcaster()) { scheduler2.Recurring(() => System.Console.WriteLine(" Recurring inner 2 5 sec"), TimeSpan.FromSeconds(6)); - //scheduler2.Recurring(() => System.Console.WriteLine(" Recurring inner 2 3 sec"), TimeSpan.FromSeconds(12)); - - System.Console.WriteLine($"Starting recurring with {Scheduler.SchedulerCount} schedulers"); scheduler2.Send(() => System.Console.WriteLine("Direct 2 message")); System.Console.ReadLine(); diff --git a/src/Tests/Broadcast.Test/Scheduling/SchedulerTests.cs b/src/Tests/Broadcast.Test/Scheduling/SchedulerTests.cs index 3108570..81f963d 100644 --- a/src/Tests/Broadcast.Test/Scheduling/SchedulerTests.cs +++ b/src/Tests/Broadcast.Test/Scheduling/SchedulerTests.cs @@ -93,29 +93,6 @@ public void Scheduler_ScheduledTasks_DelayWithProcessed() Task.Delay(1000).Wait(); Assert.AreEqual(1, scheduler.ScheduledTasks().Count()); - } - - [Test] - public void Scheduler_ThreadsCount() - { - var activeSchedulers = Scheduler.SchedulerCount; - - var scheduler1 = new Scheduler(); - var scheduler2 = new Scheduler(); - var scheduler3 = new Scheduler(); - - - - Assert.IsTrue(Scheduler.SchedulerCount == activeSchedulers + 3, $"3 {Scheduler.SchedulerCount}"); - - scheduler1.Dispose(); - Assert.AreEqual(Scheduler.SchedulerCount, activeSchedulers + 2, "2"); - - scheduler2.Dispose(); - Assert.IsTrue(Scheduler.SchedulerCount == activeSchedulers + 1, "1"); - - scheduler3.Dispose(); - Assert.IsTrue(Scheduler.SchedulerCount == activeSchedulers, "0"); } } } From fb61366c3b329b32a93bdb2bfd93b7a80f7f7e1f Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 7 Dec 2021 06:35:38 +0100 Subject: [PATCH 85/92] Update testcoverage --- .github/workflows/build.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d9a83a6..16e9c88 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,9 +43,7 @@ jobs: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} shell: powershell run: | - .\.sonar\scanner\dotnet-sonarscanner begin /k:"WickedFlame_Broadcast" /o:"wickedflame" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="src/Tests/Broadcast.Test/coverage.opencover.xml,src/Tests/Broadcast.Dashboard.Test/coverage.opencover.xml,src/Tests/Broadcast.Storage.Redis.Test/coverage.opencover.xml" + .\.sonar\scanner\dotnet-sonarscanner begin /k:"WickedFlame_Broadcast" /o:"wickedflame" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="src/Tests/**/coverage.opencover.xml" dotnet build - dotnet test src/Tests/Broadcast.Test/Broadcast.Test.csproj /p:CollectCoverage=true /p:CoverletOutputFormat=opencover - dotnet test src/Tests/Broadcast.Dashboard.Test/Broadcast.Dashboard.Test.csproj /p:CollectCoverage=true /p:CoverletOutputFormat=opencover - dotnet test src/Tests/Broadcast.Storage.Redis.Test/Broadcast.Storage.Redis.Test.csproj /p:CollectCoverage=true /p:CoverletOutputFormat=opencover + dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" \ No newline at end of file From c469d2294ad559bedf3a414870a407521c417570 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 7 Dec 2021 08:17:44 +0100 Subject: [PATCH 86/92] Revert last commit on using var --- src/Broadcast.Dashboard/Assets/js/broadcast-console.js | 2 +- src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js | 2 +- src/Broadcast.Dashboard/Assets/js/broadcast-storage.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Broadcast.Dashboard/Assets/js/broadcast-console.js b/src/Broadcast.Dashboard/Assets/js/broadcast-console.js index 7af04af..8828108 100644 --- a/src/Broadcast.Dashboard/Assets/js/broadcast-console.js +++ b/src/Broadcast.Dashboard/Assets/js/broadcast-console.js @@ -77,7 +77,7 @@ export class BroadcastConsole extends BroadcastBase { } if (consoleConfig === undefined) { - var consoleConfig = { + consoleConfig = { pollUrl: "%(RouteBasePath)/dashboard/metrics", pollInterval: 1000, position: "TopRight" diff --git a/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js b/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js index 531c269..a68e574 100644 --- a/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js +++ b/src/Broadcast.Dashboard/Assets/js/broadcast-dashboard.js @@ -349,7 +349,7 @@ export class BroadcastDashboard extends BroadcastBase { } if (dashboardConfig === undefined) { - var dashboardConfig = { + dashboardConfig = { pollUrl: "%(RouteBasePath)/dashboard/data", dashboardUrl: "%(RouteBasePath)/dashboard", pollInterval: 1000 diff --git a/src/Broadcast.Dashboard/Assets/js/broadcast-storage.js b/src/Broadcast.Dashboard/Assets/js/broadcast-storage.js index a5d2df6..90da4b8 100644 --- a/src/Broadcast.Dashboard/Assets/js/broadcast-storage.js +++ b/src/Broadcast.Dashboard/Assets/js/broadcast-storage.js @@ -120,7 +120,7 @@ ${this.createStorageValues(values)} } if (storageConfig === undefined) { - var storageConfig = { + storageConfig = { pollUrl: "%(RouteBasePath)/storage/keys", pollInterval: 2000 }; From ca18518eea0b083d88f435310b61946c75170bc0 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 7 Dec 2021 08:54:58 +0100 Subject: [PATCH 87/92] Only dispose closed threads --- src/Broadcast/Processing/ThreadList.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Broadcast/Processing/ThreadList.cs b/src/Broadcast/Processing/ThreadList.cs index 1cb03e0..1532b33 100644 --- a/src/Broadcast/Processing/ThreadList.cs +++ b/src/Broadcast/Processing/ThreadList.cs @@ -63,12 +63,11 @@ public void Remove(Task task) if (_taskList.Contains(task)) { Trace.WriteLine($"Remove Thread with state: {task.Status}"); - if (task.Status == TaskStatus.Running) + if (task.Status != TaskStatus.Running) { - task.Wait(); - } + task.Dispose(); + } - task.Dispose(); _taskList.Remove(task); } From 00191252b7974724bc2480060f97223cc6b5ff3d Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 7 Dec 2021 09:18:47 +0100 Subject: [PATCH 88/92] Don't dispose threads --- src/Broadcast/Processing/ThreadList.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Broadcast/Processing/ThreadList.cs b/src/Broadcast/Processing/ThreadList.cs index 1532b33..3000698 100644 --- a/src/Broadcast/Processing/ThreadList.cs +++ b/src/Broadcast/Processing/ThreadList.cs @@ -63,12 +63,7 @@ public void Remove(Task task) if (_taskList.Contains(task)) { Trace.WriteLine($"Remove Thread with state: {task.Status}"); - if (task.Status != TaskStatus.Running) - { - task.Dispose(); - } - - _taskList.Remove(task); + _taskList.Remove(task); } _threadCountHandler?.Invoke(this, new ThreadHandlerEventArgs { Name = _name, Count = _taskList.Count }); From 7f9f1942bf1e7fdc7c3534572462e72912b895ab Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 7 Dec 2021 09:45:30 +0100 Subject: [PATCH 89/92] Add coverlet to testprojects --- .../Broadcast.Integration.Test.csproj | 4 ++++ .../Broadcast.Storage.Integration.Test.csproj | 4 ++++ .../Broadcast.Storage.Redis.Integration.Test.csproj | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj b/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj index 32377a7..383f013 100644 --- a/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj +++ b/src/Tests/Broadcast.Integration.Test/Broadcast.Integration.Test.csproj @@ -10,6 +10,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj b/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj index ab7692a..5925f2e 100644 --- a/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj +++ b/src/Tests/Broadcast.Storage.Integration.Test/Broadcast.Storage.Integration.Test.csproj @@ -9,6 +9,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj b/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj index 56f98f7..be5ffab 100644 --- a/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj +++ b/src/Tests/Broadcast.Storage.Redis.Integration.Test/Broadcast.Storage.Redis.Integration.Test.csproj @@ -13,6 +13,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + From da1f6406cccbdec17894297937fe0a9d1804011d Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 7 Dec 2021 20:14:55 +0100 Subject: [PATCH 90/92] Delay rescheduling tasks to prevent multiple servers taking the task --- .../EventSourcing/ReschedulingDispatcher.cs | 22 +++++++++++-------- src/Broadcast/EventSourcing/TaskStore.cs | 1 + .../Behaviour/ThreadListTests.cs | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Broadcast/EventSourcing/ReschedulingDispatcher.cs b/src/Broadcast/EventSourcing/ReschedulingDispatcher.cs index e19eee2..79ee600 100644 --- a/src/Broadcast/EventSourcing/ReschedulingDispatcher.cs +++ b/src/Broadcast/EventSourcing/ReschedulingDispatcher.cs @@ -9,16 +9,13 @@ namespace Broadcast.EventSourcing ///
public class ReschedulingDispatcher : IStorageObserver { - private readonly ILogger _logger; - /// /// Creates a new instance of a ReschedulingDispatcher /// - /// public ReschedulingDispatcher() { - _logger = LoggerFactory.Create(); - _logger.Write($"Starting new ReschedulingDispatcher"); + var logger = LoggerFactory.Create(); + logger.Write($"Starting new ReschedulingDispatcher"); } /// @@ -57,10 +54,17 @@ public void Execute(ObserverContext context) // move task to enqued list context.Store.Storage(s => - { - s.RemoveFromList(new StorageKey("tasks:dequeued"), disp); - s.AddToList(new StorageKey("tasks:enqueued"), disp); - }); + { + if (!s.RemoveFromList(new StorageKey("tasks:dequeued"), disp)) + { + return; + } + + // delay rescheduling to prevent 2 servers that start the same time + // to process the task as soon as it is enqueued again + System.Threading.Tasks.Task.Delay(50).Wait(); + s.AddToList(new StorageKey("tasks:enqueued"), disp); + }); dispatch = true; diff --git a/src/Broadcast/EventSourcing/TaskStore.cs b/src/Broadcast/EventSourcing/TaskStore.cs index 0b2821f..ad3c594 100644 --- a/src/Broadcast/EventSourcing/TaskStore.cs +++ b/src/Broadcast/EventSourcing/TaskStore.cs @@ -196,6 +196,7 @@ public void RegisterDispatchers(string id, IEnumerable dispatchers) _logger.Write($"Register a new set of dispatchers to storage for {id}"); _dispatchers.Add(id, dispatchers); + // start a ReschedulingDispatcher to check if there are tasks that are not processed yet _storageObserver.Start(new ReschedulingDispatcher()); } diff --git a/src/Tests/Broadcast.Integration.Test/Behaviour/ThreadListTests.cs b/src/Tests/Broadcast.Integration.Test/Behaviour/ThreadListTests.cs index 4239476..06751a3 100644 --- a/src/Tests/Broadcast.Integration.Test/Behaviour/ThreadListTests.cs +++ b/src/Tests/Broadcast.Integration.Test/Behaviour/ThreadListTests.cs @@ -15,7 +15,7 @@ public class ThreadListTests : BDTestBase [TearDown] public void Teardown() { - Task.Delay(700).Wait(); + Task.Delay(800).Wait(); } [Test] From 75fcfeffd6f8a6f02942b0d907b67100a7beb282 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 7 Dec 2021 20:15:40 +0100 Subject: [PATCH 91/92] Start a new Broadcaster uses a isolated storage for tasks --- src/Broadcast/Broadcaster.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Broadcast/Broadcaster.cs b/src/Broadcast/Broadcaster.cs index 7a147b9..479b69f 100644 --- a/src/Broadcast/Broadcaster.cs +++ b/src/Broadcast/Broadcaster.cs @@ -27,7 +27,8 @@ public class Broadcaster : IBroadcaster /// /// Creates a new Broadcaster /// - public Broadcaster() : this(TaskStore.Default) + public Broadcaster() + : this(new TaskStore()) { } From 07c43dea8218a5539288336b46731776eb858452 Mon Sep 17 00:00:00 2001 From: Christian Walpen Date: Tue, 7 Dec 2021 20:32:18 +0100 Subject: [PATCH 92/92] Storageobserver waits for all threads to end --- src/Broadcast/EventSourcing/StorageObserver.cs | 1 + .../Broadcast.Test/EventSourcing/StorageObserverTests.cs | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Broadcast/EventSourcing/StorageObserver.cs b/src/Broadcast/EventSourcing/StorageObserver.cs index a4ff1c9..744a758 100644 --- a/src/Broadcast/EventSourcing/StorageObserver.cs +++ b/src/Broadcast/EventSourcing/StorageObserver.cs @@ -86,6 +86,7 @@ public void Start(IStorageObserver observer) public void Dispose() { _threadWait.Dispose(); + _process.WaitAll(); } } } diff --git a/src/Tests/Broadcast.Test/EventSourcing/StorageObserverTests.cs b/src/Tests/Broadcast.Test/EventSourcing/StorageObserverTests.cs index 90a747e..720c162 100644 --- a/src/Tests/Broadcast.Test/EventSourcing/StorageObserverTests.cs +++ b/src/Tests/Broadcast.Test/EventSourcing/StorageObserverTests.cs @@ -30,10 +30,10 @@ public void StorageObserver_StartNew() store.Setup(x => x.GetEnumerator()).Returns(new List().GetEnumerator()); var task = new TestObserver(); - var observer = new StorageObserver(store.Object, new Options()); - observer.Start(task); - - Task.Delay(50).Wait(); + using (var observer = new StorageObserver(store.Object, new Options())) + { + observer.Start(task); + } Assert.IsTrue(task.Executed); }