From 0499b3a5e04487d187ea01aa1012f296c6007031 Mon Sep 17 00:00:00 2001 From: "Matthew M. Keeler" Date: Sat, 14 Mar 2020 23:45:38 -0400 Subject: [PATCH 001/342] Add prefix support for AWS Queues Fixes #521 --- src/providers/WorkflowCore.Providers.AWS/README.md | 2 +- .../ServiceCollectionExtensions.cs | 4 ++-- .../Services/SQSQueueProvider.cs | 10 ++++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/providers/WorkflowCore.Providers.AWS/README.md b/src/providers/WorkflowCore.Providers.AWS/README.md index b0717fc36..f9c000662 100644 --- a/src/providers/WorkflowCore.Providers.AWS/README.md +++ b/src/providers/WorkflowCore.Providers.AWS/README.md @@ -27,7 +27,7 @@ services.AddWorkflow(cfg => { cfg.UseAwsDynamoPersistence(new EnvironmentVariablesAWSCredentials(), new AmazonDynamoDBConfig() { RegionEndpoint = RegionEndpoint.USWest2 }, "table-prefix"); cfg.UseAwsDynamoLocking(new EnvironmentVariablesAWSCredentials(), new AmazonDynamoDBConfig() { RegionEndpoint = RegionEndpoint.USWest2 }, "workflow-core-locks"); - cfg.UseAwsSimpleQueueService(new EnvironmentVariablesAWSCredentials(), new AmazonSQSConfig() { RegionEndpoint = RegionEndpoint.USWest2 }); + cfg.UseAwsSimpleQueueService(new EnvironmentVariablesAWSCredentials(), new AmazonSQSConfig() { RegionEndpoint = RegionEndpoint.USWest2 }, "queues-prefix"); }); ``` diff --git a/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs index 6c32f1571..bb43a3397 100644 --- a/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs @@ -13,9 +13,9 @@ namespace Microsoft.Extensions.DependencyInjection { public static class ServiceCollectionExtensions { - public static WorkflowOptions UseAwsSimpleQueueService(this WorkflowOptions options, AWSCredentials credentials, AmazonSQSConfig config) + public static WorkflowOptions UseAwsSimpleQueueService(this WorkflowOptions options, AWSCredentials credentials, AmazonSQSConfig config, string queuesPrefix = "workflowcore") { - options.UseQueueProvider(sp => new SQSQueueProvider(credentials, config, sp.GetService())); + options.UseQueueProvider(sp => new SQSQueueProvider(credentials, config, sp.GetService(), queuesPrefix)); return options; } diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/SQSQueueProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/SQSQueueProvider.cs index 6daed010b..dd1c15e14 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/SQSQueueProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/SQSQueueProvider.cs @@ -17,13 +17,15 @@ public class SQSQueueProvider : IQueueProvider private readonly ILogger _logger; private readonly IAmazonSQS _client; private readonly Dictionary _queues = new Dictionary(); + private readonly string _queuesPrefix; public bool IsDequeueBlocking => true; - public SQSQueueProvider(AWSCredentials credentials, AmazonSQSConfig config, ILoggerFactory logFactory) + public SQSQueueProvider(AWSCredentials credentials, AmazonSQSConfig config, ILoggerFactory logFactory, string queuesPrefix) { _logger = logFactory.CreateLogger(); _client = new AmazonSQSClient(credentials, config); + _queuesPrefix = queuesPrefix; } public async Task QueueWork(string id, QueueType queue) @@ -54,9 +56,9 @@ public async Task DequeueWork(QueueType queue, CancellationToken cancell public async Task Start() { - var workflowQueue = await _client.CreateQueueAsync(new CreateQueueRequest("workflowcore-workflows")); - var eventQueue = await _client.CreateQueueAsync(new CreateQueueRequest("workflowcore-events")); - var indexQueue = await _client.CreateQueueAsync(new CreateQueueRequest("workflowcore-index")); + var workflowQueue = await _client.CreateQueueAsync(new CreateQueueRequest($"{_queuesPrefix}-workflows")); + var eventQueue = await _client.CreateQueueAsync(new CreateQueueRequest($"{_queuesPrefix}-events")); + var indexQueue = await _client.CreateQueueAsync(new CreateQueueRequest($"{_queuesPrefix}-index")); _queues[QueueType.Workflow] = workflowQueue.QueueUrl; _queues[QueueType.Event] = eventQueue.QueueUrl; From 12e813370727ca258508ba6bbd3696a2d607afe9 Mon Sep 17 00:00:00 2001 From: Mark Tinsley Date: Wed, 1 Apr 2020 11:23:17 -0500 Subject: [PATCH 002/342] Tiny wording fix --- docs/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 48ee3b904..49ac1f38e 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -20,7 +20,7 @@ public class HelloWorld : StepBody ``` *The `StepBody` and `StepBodyAsync` class implementations are constructed by the workflow host which first tries to use IServiceProvider for dependency injection, if it can't construct it with this method, it will search for a parameterless constructor* -### Then we define the workflow structure by composing a chain of steps. The is done by implementing the IWorkflow interface +### Then we define the workflow structure by composing a chain of steps. This is done by implementing the IWorkflow interface ```C# public class HelloWorldWorkflow : IWorkflow From da86d9a30cbea4d7853c95fdd2e4a352e55dea4f Mon Sep 17 00:00:00 2001 From: eduardocalixtoviasoft <42845879+eduardocalixtoviasoft@users.noreply.github.com> Date: Wed, 8 Apr 2020 10:01:31 -0300 Subject: [PATCH 003/342] Spelling correction Fix readme file "comeplete" to "complete" --- src/samples/WorkflowCore.Sample03/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/samples/WorkflowCore.Sample03/README.md b/src/samples/WorkflowCore.Sample03/README.md index d75950de6..02e8f730a 100644 --- a/src/samples/WorkflowCore.Sample03/README.md +++ b/src/samples/WorkflowCore.Sample03/README.md @@ -50,7 +50,7 @@ public class PassingDataWorkflow : IWorkflow .Input(step => step.Message, data => "The answer is " + data.Value3.ToString()) .Then(context => { - Console.WriteLine("Workflow comeplete"); + Console.WriteLine("Workflow complete"); return ExecutionResult.Next(); }); } From f87c1bd27aa7f435e85a4379ac23637eb50219a8 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 24 Apr 2020 16:20:51 +0200 Subject: [PATCH 004/342] add test for compensate with seq --- .../Scenarios/CompensationScenario2.cs | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario2.cs diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario2.cs b/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario2.cs new file mode 100644 index 000000000..2b2000304 --- /dev/null +++ b/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario2.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Text; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using Xunit; +using FluentAssertions; +using System.Linq; +using WorkflowCore.Testing; + +namespace WorkflowCore.IntegrationTests.Scenarios +{ + public class CompensationScenario2 : WorkflowTest + { + public class MyDataClass + { + public bool ThrowException { get; set; } + } + + public class Workflow : IWorkflow + { + public static bool Event1Fired = false; + public static bool Event2Fired = false; + public static bool TailEventFired = false; + public static bool Compensation1Fired = false; + public static bool Compensation2Fired = false; + + public string Id => "CompensationWorkflow2"; + public int Version => 1; + public void Build(IWorkflowBuilder builder) + { + builder + .StartWith(context => ExecutionResult.Next()) + .Then(context => + { + Event1Fired = true; + if ((context.Workflow.Data as MyDataClass).ThrowException) + throw new Exception(); + Event2Fired = true; + }) + .CompensateWithSequence(seq => seq + .StartWith(context => Compensation1Fired = true) + .Then(context => Compensation2Fired = true) + ) + .Then(context => TailEventFired = true); + } + } + + public CompensationScenario2() + { + Setup(); + Workflow.Event1Fired = false; + Workflow.Event2Fired = false; + Workflow.Compensation1Fired = false; + Workflow.Compensation2Fired = false; + Workflow.TailEventFired = false; + } + + [Fact] + public void NoExceptionScenario() + { + var workflowId = StartWorkflow(new MyDataClass() { ThrowException = false }); + WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); + + GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); + UnhandledStepErrors.Count.Should().Be(0); + Workflow.Event1Fired.Should().BeTrue(); + Workflow.Event2Fired.Should().BeTrue(); + Workflow.Compensation1Fired.Should().BeFalse(); + Workflow.Compensation2Fired.Should().BeFalse(); + Workflow.TailEventFired.Should().BeTrue(); + } + + [Fact] + public void ExceptionScenario() + { + var workflowId = StartWorkflow(new MyDataClass() { ThrowException = true }); + WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); + + GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); + UnhandledStepErrors.Count.Should().Be(1); + Workflow.Event1Fired.Should().BeTrue(); + Workflow.Event2Fired.Should().BeFalse(); + Workflow.Compensation1Fired.Should().BeTrue(); + Workflow.Compensation2Fired.Should().BeTrue(); + Workflow.TailEventFired.Should().BeTrue(); + } + } +} From e556030c4f53a058dbd54ae35207f9eaa9d63052 Mon Sep 17 00:00:00 2001 From: Aleksei Petrov Date: Tue, 12 May 2020 10:09:44 +0300 Subject: [PATCH 005/342] Fix PostgreSQL environment variables --- test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs b/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs index 79161fdb5..c5e1d93b1 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs @@ -19,6 +19,10 @@ public class PostgresDockerSetup : DockerSetup public override string ImageName => "postgres"; public override int InternalPort => 5432; + private const string PostgresHostAuthMethod = "trust"; + public override IList EnvironmentVariables => new List { + $"POSTGRES_HOST_AUTH_METHOD={PostgresHostAuthMethod}" + }; public override void PublishConnectionInfo() { ConnectionString = $"Server=127.0.0.1;Port={ExternalPort};Database=workflow;User Id=postgres;"; From de6410d7b97497f57168e7ae897d059408265000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BB=92=E7=AB=B9=20=E5=90=B3?= Date: Tue, 19 May 2020 14:25:35 +0800 Subject: [PATCH 006/342] Add Using WorkFlowCore.DSL in README YAML&JSON Part --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7faad2599..a7dac4994 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ public class MyWorkflow : IWorkflow ## JSON / YAML Workflow Definitions -Define your workflows in JSON or YAML +Define your workflows in JSON or YAML, need to install WorkFlowCore.DSL ```json { @@ -65,7 +65,7 @@ Steps: StepType: MyApp.GoodbyeWorld, MyApp ``` -### Sample use cases +## Sample use cases * New user workflow ```c# From 6ba5040ebccbc8a8bca48beab5b2dc1fdd85865a Mon Sep 17 00:00:00 2001 From: glucaci Date: Mon, 8 Jun 2020 14:57:35 +0200 Subject: [PATCH 007/342] Allow dependency injection on Workflow --- src/WorkflowCore/Interface/IWorkflowController.cs | 4 ++-- src/WorkflowCore/Services/WorkflowController.cs | 13 ++++++++----- src/WorkflowCore/Services/WorkflowHost.cs | 11 +++++------ 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/WorkflowCore/Interface/IWorkflowController.cs b/src/WorkflowCore/Interface/IWorkflowController.cs index 757351351..89e7fc3c6 100644 --- a/src/WorkflowCore/Interface/IWorkflowController.cs +++ b/src/WorkflowCore/Interface/IWorkflowController.cs @@ -13,8 +13,8 @@ public interface IWorkflowController Task StartWorkflow(string workflowId, int? version, TData data = null, string reference=null) where TData : class, new(); Task PublishEvent(string eventName, string eventKey, object eventData, DateTime? effectiveDate = null); - void RegisterWorkflow() where TWorkflow : IWorkflow, new(); - void RegisterWorkflow() where TWorkflow : IWorkflow, new() where TData : new(); + void RegisterWorkflow() where TWorkflow : IWorkflow; + void RegisterWorkflow() where TWorkflow : IWorkflow where TData : new(); /// /// Suspend the execution of a given workflow until .ResumeWorkflow is called diff --git a/src/WorkflowCore/Services/WorkflowController.cs b/src/WorkflowCore/Services/WorkflowController.cs index fc7c7b810..203da3139 100755 --- a/src/WorkflowCore/Services/WorkflowController.cs +++ b/src/WorkflowCore/Services/WorkflowController.cs @@ -3,6 +3,7 @@ using System.Reflection; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using WorkflowCore.Exceptions; using WorkflowCore.Interface; @@ -19,9 +20,10 @@ public class WorkflowController : IWorkflowController private readonly IQueueProvider _queueProvider; private readonly IExecutionPointerFactory _pointerFactory; private readonly ILifeCycleEventHub _eventHub; + private readonly IServiceProvider _serviceProvider; private readonly ILogger _logger; - public WorkflowController(IPersistenceProvider persistenceStore, IDistributedLockProvider lockProvider, IWorkflowRegistry registry, IQueueProvider queueProvider, IExecutionPointerFactory pointerFactory, ILifeCycleEventHub eventHub, ILoggerFactory loggerFactory) + public WorkflowController(IPersistenceProvider persistenceStore, IDistributedLockProvider lockProvider, IWorkflowRegistry registry, IQueueProvider queueProvider, IExecutionPointerFactory pointerFactory, ILifeCycleEventHub eventHub, ILoggerFactory loggerFactory, IServiceProvider serviceProvider) { _persistenceStore = persistenceStore; _lockProvider = lockProvider; @@ -29,6 +31,7 @@ public WorkflowController(IPersistenceProvider persistenceStore, IDistributedLoc _queueProvider = queueProvider; _pointerFactory = pointerFactory; _eventHub = eventHub; + _serviceProvider = serviceProvider; _logger = loggerFactory.CreateLogger(); } @@ -213,17 +216,17 @@ await _eventHub.PublishNotification(new WorkflowTerminated() } public void RegisterWorkflow() - where TWorkflow : IWorkflow, new() + where TWorkflow : IWorkflow { - TWorkflow wf = new TWorkflow(); + TWorkflow wf = ActivatorUtilities.CreateInstance(_serviceProvider); _registry.RegisterWorkflow(wf); } public void RegisterWorkflow() - where TWorkflow : IWorkflow, new() + where TWorkflow : IWorkflow where TData : new() { - TWorkflow wf = new TWorkflow(); + TWorkflow wf = ActivatorUtilities.CreateInstance(_serviceProvider); _registry.RegisterWorkflow(wf); } } diff --git a/src/WorkflowCore/Services/WorkflowHost.cs b/src/WorkflowCore/Services/WorkflowHost.cs index 9092e6487..aa08ba727 100644 --- a/src/WorkflowCore/Services/WorkflowHost.cs +++ b/src/WorkflowCore/Services/WorkflowHost.cs @@ -7,6 +7,7 @@ using WorkflowCore.Interface; using WorkflowCore.Models; using System.Reflection; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.Exceptions; using WorkflowCore.Models.LifeCycleEvents; @@ -121,18 +122,16 @@ public async Task StopAsync(CancellationToken cancellationToken) } public void RegisterWorkflow() - where TWorkflow : IWorkflow, new() + where TWorkflow : IWorkflow { - TWorkflow wf = new TWorkflow(); - Registry.RegisterWorkflow(wf); + _workflowController.RegisterWorkflow(); } public void RegisterWorkflow() - where TWorkflow : IWorkflow, new() + where TWorkflow : IWorkflow where TData : new() { - TWorkflow wf = new TWorkflow(); - Registry.RegisterWorkflow(wf); + _workflowController.RegisterWorkflow(); } public Task SuspendWorkflow(string workflowId) From 3485fd01718a9075265963fbf5e29ef55cba4a86 Mon Sep 17 00:00:00 2001 From: "Matthew M. Keeler" Date: Wed, 17 Jun 2020 00:24:41 -0400 Subject: [PATCH 008/342] Update AWS provider versions --- .../WorkflowCore.Providers.AWS.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj index d8470de03..84eb6cb74 100644 --- a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj +++ b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj @@ -11,9 +11,9 @@ https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core.git git - 3.0.1 - 3.0.1.0 - 3.0.1 + 3.0.2 + 3.0.2.0 + 3.0.2 From 8d2ee35927d5c36658f5cd5c8f85278b75d90a5d Mon Sep 17 00:00:00 2001 From: Nikita Kirsanov Date: Thu, 18 Jun 2020 12:55:38 +0700 Subject: [PATCH 009/342] Update mkdocs.yml fix little typo --- mkdocs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 1081d0f05..fcbf9e4a8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,7 +4,7 @@ nav: - Getting started: getting-started.md - External events: external-events.md - Activity workers: activities.md - - Error handing: error-handling.md + - Error handling: error-handling.md - Control structures: control-structures.md - Saga transactions: sagas.md - JSON / YAML Definitions: json-yaml.md @@ -15,4 +15,4 @@ nav: - Test helpers: test-helpers.md - Extensions: extensions.md - Samples: samples.md -theme: readthedocs \ No newline at end of file +theme: readthedocs From 40e97ecd0b64e6807148c6e12976f5052e803dbd Mon Sep 17 00:00:00 2001 From: glucaci Date: Thu, 18 Jun 2020 08:50:06 +0200 Subject: [PATCH 010/342] Increment version --- src/WorkflowCore/WorkflowCore.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 27960af9e..920413a73 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,9 +15,9 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.1.5 - 3.1.5.0 - 3.1.5.0 + 3.1.6 + 3.1.6.0 + 3.1.6.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png 3.1.5 From cb6c290fa803fb51bf71a1514c438b6013475530 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 23 Jun 2020 18:34:33 -0700 Subject: [PATCH 011/342] Update elastic-search.md --- docs/elastic-search.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/elastic-search.md b/docs/elastic-search.md index ce187de80..e921f958d 100644 --- a/docs/elastic-search.md +++ b/docs/elastic-search.md @@ -21,7 +21,7 @@ dotnet add package WorkflowCore.Providers.Elasticsearch Use the `.UseElasticsearch` extension method on `IServiceCollection` when building your service provider -```C# +``` using Nest; ... services.AddWorkflow(cfg => @@ -50,7 +50,7 @@ This will do a full text search on the following default fields In addition you can search data within your own custom data object if it implements `ISearchable` - ```c# + ``` using WorkflowCore.Interfaces; ... public class MyData : ISearchable @@ -72,7 +72,7 @@ This will do a full text search on the following default fields ##### Examples Search all fields for "puppies" - ```c# + ``` searchIndex.Search("puppies", 0, 10); ``` @@ -96,7 +96,7 @@ The following filter types are available ##### Examples Filtering by reference - ```c# + ``` using WorkflowCore.Models.Search; ... @@ -104,22 +104,22 @@ The following filter types are available ``` Filtering by workflows started after a date - ```c# + ``` searchIndex.Search("", 0, 10, DateRangeFilter.After(x => x.CreateTime, startDate)); ``` Filtering by workflows completed within a period - ```c# + ``` searchIndex.Search("", 0, 10, DateRangeFilter.Between(x => x.CompleteTime, startDate, endDate)); ``` Filtering by workflows in a state - ```c# + ``` searchIndex.Search("", 0, 10, StatusFilter.Equals(WorkflowStatus.Complete)); ``` Filtering against your own custom data class - ```c# + ``` class MyData { From 7df09a6fcf82ca307672b14a0eca26669cea2a75 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 3 Jul 2020 16:46:19 -0700 Subject: [PATCH 012/342] Update WorkflowCore.csproj --- src/WorkflowCore/WorkflowCore.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 920413a73..fca9b4de3 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -20,7 +20,7 @@ 3.1.6.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.1.5 + 3.1.6 From dac9b30b12b973632771bb4344879588b6f71f3b Mon Sep 17 00:00:00 2001 From: Leon Segal Date: Sun, 5 Jul 2020 14:44:58 +0200 Subject: [PATCH 013/342] #274 add registry.getAllDefinitions to retrieve all registered workflows --- src/WorkflowCore/Interface/IWorkflowRegistry.cs | 4 +++- src/WorkflowCore/Services/WorkflowRegistry.cs | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/WorkflowCore/Interface/IWorkflowRegistry.cs b/src/WorkflowCore/Interface/IWorkflowRegistry.cs index 6f798b8e7..40143e3c1 100644 --- a/src/WorkflowCore/Interface/IWorkflowRegistry.cs +++ b/src/WorkflowCore/Interface/IWorkflowRegistry.cs @@ -1,4 +1,5 @@ -using WorkflowCore.Models; +using System.Collections.Generic; +using WorkflowCore.Models; namespace WorkflowCore.Interface { @@ -10,5 +11,6 @@ public interface IWorkflowRegistry WorkflowDefinition GetDefinition(string workflowId, int? version = null); bool IsRegistered(string workflowId, int version); void DeregisterWorkflow(string workflowId, int version); + IEnumerable GetAllDefinitions(); } } diff --git a/src/WorkflowCore/Services/WorkflowRegistry.cs b/src/WorkflowCore/Services/WorkflowRegistry.cs index 8ed6a6f7b..5677d434d 100644 --- a/src/WorkflowCore/Services/WorkflowRegistry.cs +++ b/src/WorkflowCore/Services/WorkflowRegistry.cs @@ -84,5 +84,10 @@ public bool IsRegistered(string workflowId, int version) var definition = _registry.Find(x => x.Item1 == workflowId && x.Item2 == version); return (definition != null); } + + public IEnumerable GetAllDefinitions() + { + return _registry.Select(i => i.Item3); + } } } From db293fc08de4c012eb5030f90eaac7fc8687bfa6 Mon Sep 17 00:00:00 2001 From: Leon Segal Date: Fri, 10 Jul 2020 14:09:29 +0200 Subject: [PATCH 014/342] add foreach.RunParallel option to allow synchronous execution of child branches --- README.md | 2 + WorkflowCore.sln | 7 ++ src/WorkflowCore/Interface/IStepBuilder.cs | 7 ++ .../Models/IteratorPersistenceData.cs | 7 ++ src/WorkflowCore/Primitives/Foreach.cs | 31 +++++++-- .../Services/FluentBuilders/StepBuilder.cs | 19 ++++++ .../Services/MongoPersistenceProvider.cs | 1 + src/samples/WorkflowCore.Sample09/README.md | 4 +- .../ForEachSyncWorkflow.cs | 26 ++++++++ src/samples/WorkflowCore.Sample09s/Program.cs | 45 +++++++++++++ src/samples/WorkflowCore.Sample09s/README.md | 29 +++++++++ .../Steps/DisplayContext.cs | 20 ++++++ .../Steps/DoSomething.cs | 17 +++++ .../Steps/SayGoodbye.cs | 17 +++++ .../WorkflowCore.Sample09s/Steps/SayHello.cs | 17 +++++ .../WorkflowCore.Sample09s.csproj | 19 ++++++ .../Scenarios/ForeachSyncScenario.cs | 64 +++++++++++++++++++ 17 files changed, 323 insertions(+), 9 deletions(-) create mode 100644 src/WorkflowCore/Models/IteratorPersistenceData.cs create mode 100644 src/samples/WorkflowCore.Sample09s/ForEachSyncWorkflow.cs create mode 100644 src/samples/WorkflowCore.Sample09s/Program.cs create mode 100644 src/samples/WorkflowCore.Sample09s/README.md create mode 100644 src/samples/WorkflowCore.Sample09s/Steps/DisplayContext.cs create mode 100644 src/samples/WorkflowCore.Sample09s/Steps/DoSomething.cs create mode 100644 src/samples/WorkflowCore.Sample09s/Steps/SayGoodbye.cs create mode 100644 src/samples/WorkflowCore.Sample09s/Steps/SayHello.cs create mode 100644 src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj create mode 100644 test/WorkflowCore.IntegrationTests/Scenarios/ForeachSyncScenario.cs diff --git a/README.md b/README.md index a7dac4994..9c55cc475 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,8 @@ These are also available as separate Nuget packages. * [Parallel ForEach](src/samples/WorkflowCore.Sample09) +* [Sync ForEach](src/samples/WorkflowCore.Sample09s) + * [While Loop](src/samples/WorkflowCore.Sample10) * [If Statement](src/samples/WorkflowCore.Sample11) diff --git a/WorkflowCore.sln b/WorkflowCore.sln index 047ccf0c3..81030f058 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -141,6 +141,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.DSL", "src\Wor EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample18", "src\samples\WorkflowCore.Sample18\WorkflowCore.Sample18.csproj", "{5BE6D628-B9DB-4C76-AAEB-8F3800509A84}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Sample09s", "src\samples\WorkflowCore.Sample09s\WorkflowCore.Sample09s.csproj", "{E32CF21A-29CC-46D1-8044-FCC327F2B281}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -343,6 +345,10 @@ Global {5BE6D628-B9DB-4C76-AAEB-8F3800509A84}.Debug|Any CPU.Build.0 = Debug|Any CPU {5BE6D628-B9DB-4C76-AAEB-8F3800509A84}.Release|Any CPU.ActiveCfg = Release|Any CPU {5BE6D628-B9DB-4C76-AAEB-8F3800509A84}.Release|Any CPU.Build.0 = Release|Any CPU + {E32CF21A-29CC-46D1-8044-FCC327F2B281}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E32CF21A-29CC-46D1-8044-FCC327F2B281}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E32CF21A-29CC-46D1-8044-FCC327F2B281}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E32CF21A-29CC-46D1-8044-FCC327F2B281}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -400,6 +406,7 @@ Global {78217204-B873-40B9-8875-E3925B2FBCEC} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} {20B98905-08CB-4854-8E2C-A31A078383E9} = {EF47161E-E399-451C-BDE8-E92AAD3BD761} {5BE6D628-B9DB-4C76-AAEB-8F3800509A84} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} + {E32CF21A-29CC-46D1-8044-FCC327F2B281} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC0FA8D3-6449-4FDA-BB46-ECF58FAD23B4} diff --git a/src/WorkflowCore/Interface/IStepBuilder.cs b/src/WorkflowCore/Interface/IStepBuilder.cs index db28b5887..d5ebcec7b 100644 --- a/src/WorkflowCore/Interface/IStepBuilder.cs +++ b/src/WorkflowCore/Interface/IStepBuilder.cs @@ -186,6 +186,13 @@ public interface IStepBuilder /// IContainerStepBuilder ForEach(Expression> collection); + /// + /// Execute a block of steps, once for each item in a collection in a RunParallel foreach + /// + /// Resolves a collection for iterate over + /// + IContainerStepBuilder ForEach(Expression> collection, Expression> runParallel); + /// /// Repeat a block of steps until a condition becomes true /// diff --git a/src/WorkflowCore/Models/IteratorPersistenceData.cs b/src/WorkflowCore/Models/IteratorPersistenceData.cs new file mode 100644 index 000000000..1d5ee1b8b --- /dev/null +++ b/src/WorkflowCore/Models/IteratorPersistenceData.cs @@ -0,0 +1,7 @@ +namespace WorkflowCore.Models +{ + public class IteratorPersistenceData : ControlPersistenceData + { + public int Index { get; set; } = 0; + } +} diff --git a/src/WorkflowCore/Primitives/Foreach.cs b/src/WorkflowCore/Primitives/Foreach.cs index 23cecc947..dd4454583 100644 --- a/src/WorkflowCore/Primitives/Foreach.cs +++ b/src/WorkflowCore/Primitives/Foreach.cs @@ -8,28 +8,45 @@ namespace WorkflowCore.Primitives { public class Foreach : ContainerStepBody { - public IEnumerable Collection { get; set; } + public IEnumerable Collection { get; set; } + public bool RunParallel { get; set; } = true; public override ExecutionResult Run(IStepExecutionContext context) { if (context.PersistenceData == null) { var values = Collection.Cast(); - return ExecutionResult.Branch(new List(values), new ControlPersistenceData() { ChildrenActive = true }); + if (RunParallel) + { + return ExecutionResult.Branch(new List(values), new IteratorPersistenceData() { ChildrenActive = true }); + } + else + { + return ExecutionResult.Branch(new List(new object[] { values.ElementAt(0) }), new IteratorPersistenceData() { ChildrenActive = true }); + } } - if (context.PersistenceData is ControlPersistenceData) + if (context.PersistenceData is IteratorPersistenceData persistanceData && persistanceData?.ChildrenActive == true) { - if ((context.PersistenceData as ControlPersistenceData).ChildrenActive) + if (context.Workflow.IsBranchComplete(context.ExecutionPointer.Id)) { - if (context.Workflow.IsBranchComplete(context.ExecutionPointer.Id)) + if (!RunParallel) { - return ExecutionResult.Next(); + var values = Collection.Cast(); + persistanceData.Index++; + if (persistanceData.Index < values.Count()) + { + return ExecutionResult.Branch(new List(new object[] { values.ElementAt(persistanceData.Index) }), persistanceData); + } } + + return ExecutionResult.Next(); } + + return ExecutionResult.Persist(persistanceData); } return ExecutionResult.Persist(context.PersistenceData); - } + } } } diff --git a/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs b/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs index 93f965eba..e1d4dcc76 100644 --- a/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs +++ b/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs @@ -306,6 +306,25 @@ public IContainerStepBuilder ForEach(Expression ForEach(Expression> collection, Expression> runParallel) + { + var newStep = new WorkflowStep(); + + Expression> inputExpr = (x => x.Collection); + newStep.Inputs.Add(new MemberMapParameter(collection, inputExpr)); + + Expression> pExpr = (x => x.RunParallel); + newStep.Inputs.Add(new MemberMapParameter(runParallel, pExpr)); + + WorkflowBuilder.AddStep(newStep); + var stepBuilder = new StepBuilder(WorkflowBuilder, newStep); + + Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + + return stepBuilder; + } + + public IContainerStepBuilder While(Expression> condition) { var newStep = new WorkflowStep(); diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index 8edd69615..40d4e5409 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -79,6 +79,7 @@ static MongoPersistenceProvider() BsonClassMap.RegisterClassMap(x => x.AutoMap()); BsonClassMap.RegisterClassMap(x => x.AutoMap()); + BsonClassMap.RegisterClassMap(x => x.AutoMap()); } static bool indexesCreated = false; diff --git a/src/samples/WorkflowCore.Sample09/README.md b/src/samples/WorkflowCore.Sample09/README.md index 9c7b54bc8..a9b2fbe2a 100644 --- a/src/samples/WorkflowCore.Sample09/README.md +++ b/src/samples/WorkflowCore.Sample09/README.md @@ -1,4 +1,4 @@ -# Foreach sample +# Foreach Parallel sample Illustrates how to implement a parallel foreach within your workflow. @@ -14,7 +14,7 @@ builder .Then(); ``` -or get the collectioin from workflow data. +or get the collection from workflow data. ```c# builder diff --git a/src/samples/WorkflowCore.Sample09s/ForEachSyncWorkflow.cs b/src/samples/WorkflowCore.Sample09s/ForEachSyncWorkflow.cs new file mode 100644 index 000000000..685b69ed1 --- /dev/null +++ b/src/samples/WorkflowCore.Sample09s/ForEachSyncWorkflow.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Sample09s +{ + public class ForEachSyncWorkflow : IWorkflow + { + public string Id => "ForeachSync"; + public int Version => 1; + + public void Build(IWorkflowBuilder builder) + { + builder + .StartWith() + .ForEach(data => new List() { 1, 2, 3, 4 }, data => false) + .Do(x => x + .StartWith() + .Input(step => step.Item, (data, context) => context.Item) + .Then()) + .Then(); + } + } +} diff --git a/src/samples/WorkflowCore.Sample09s/Program.cs b/src/samples/WorkflowCore.Sample09s/Program.cs new file mode 100644 index 000000000..9fd4dcb0f --- /dev/null +++ b/src/samples/WorkflowCore.Sample09s/Program.cs @@ -0,0 +1,45 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System; +using WorkflowCore.Interface; + +namespace WorkflowCore.Sample09s +{ + class Program + { + public static void Main(string[] args) + { + IServiceProvider serviceProvider = ConfigureServices(); + + //start the workflow host + var host = serviceProvider.GetService(); + host.RegisterWorkflow(); + host.Start(); + + Console.WriteLine("Starting workflow..."); + string workflowId = host.StartWorkflow("Foreach").Result; + + + Console.ReadLine(); + host.Stop(); + } + + private static IServiceProvider ConfigureServices() + { + //setup dependency injection + IServiceCollection services = new ServiceCollection(); + services.AddLogging(); + services.AddWorkflow(); + //services.AddWorkflow(x => x.UseMongoDB(@"mongodb://localhost:27017", "workflow-test002")); + //services.AddWorkflow(x => x.UseSqlServer(@"Server=.;Database=WorkflowCore3;Trusted_Connection=True;", true, true)); + //services.AddWorkflow(x => x.UseSqlite(@"Data Source=database2.db;", true)); + //services.AddWorkflow(x => x.UsePostgreSQL(@"Server=127.0.0.1;Port=32768;Database=workflow_test002;User Id=postgres;", true, true)); + + + var serviceProvider = services.BuildServiceProvider(); + + return serviceProvider; + } + + } +} \ No newline at end of file diff --git a/src/samples/WorkflowCore.Sample09s/README.md b/src/samples/WorkflowCore.Sample09s/README.md new file mode 100644 index 000000000..ea6efae02 --- /dev/null +++ b/src/samples/WorkflowCore.Sample09s/README.md @@ -0,0 +1,29 @@ +# Foreach Sync sample + +Illustrates how to implement a synchronous foreach within your workflow. + + +```c# +builder + .StartWith() + .ForEach(data => new List() { 1, 2, 3, 4 }, data => false) + .Do(x => x + .StartWith() + .Input(step => step.Item, (data, context) => context.Item) + .Then()) + .Then(); +``` + +or get the collection from workflow data. + +```c# +builder + .StartWith() + .ForEach(data => data.MyCollection, data => false) + .Do(x => x + .StartWith() + .Input(step => step.Item, (data, context) => context.Item) + .Then()) + .Then(); + +``` diff --git a/src/samples/WorkflowCore.Sample09s/Steps/DisplayContext.cs b/src/samples/WorkflowCore.Sample09s/Steps/DisplayContext.cs new file mode 100644 index 000000000..d7ef216b3 --- /dev/null +++ b/src/samples/WorkflowCore.Sample09s/Steps/DisplayContext.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Sample09s +{ + public class DisplayContext : StepBody + { + + public object Item { get; set; } + + public override ExecutionResult Run(IStepExecutionContext context) + { + Console.WriteLine($"Working on item {Item}"); + return ExecutionResult.Next(); + } + } +} diff --git a/src/samples/WorkflowCore.Sample09s/Steps/DoSomething.cs b/src/samples/WorkflowCore.Sample09s/Steps/DoSomething.cs new file mode 100644 index 000000000..39344b389 --- /dev/null +++ b/src/samples/WorkflowCore.Sample09s/Steps/DoSomething.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Sample09s +{ + public class DoSomething : StepBody + { + public override ExecutionResult Run(IStepExecutionContext context) + { + Console.WriteLine("Doing something..."); + return ExecutionResult.Next(); + } + } +} diff --git a/src/samples/WorkflowCore.Sample09s/Steps/SayGoodbye.cs b/src/samples/WorkflowCore.Sample09s/Steps/SayGoodbye.cs new file mode 100644 index 000000000..34c74103b --- /dev/null +++ b/src/samples/WorkflowCore.Sample09s/Steps/SayGoodbye.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Sample09s +{ + public class SayGoodbye : StepBody + { + public override ExecutionResult Run(IStepExecutionContext context) + { + Console.WriteLine("Goodbye"); + return ExecutionResult.Next(); + } + } +} diff --git a/src/samples/WorkflowCore.Sample09s/Steps/SayHello.cs b/src/samples/WorkflowCore.Sample09s/Steps/SayHello.cs new file mode 100644 index 000000000..1597910f5 --- /dev/null +++ b/src/samples/WorkflowCore.Sample09s/Steps/SayHello.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Sample09s +{ + public class SayHello : StepBody + { + public override ExecutionResult Run(IStepExecutionContext context) + { + Console.WriteLine("Hello"); + return ExecutionResult.Next(); + } + } +} diff --git a/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj b/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj new file mode 100644 index 000000000..e569ec895 --- /dev/null +++ b/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj @@ -0,0 +1,19 @@ + + + + Exe + netcoreapp3.0 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ForeachSyncScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ForeachSyncScenario.cs new file mode 100644 index 000000000..61cf3484c --- /dev/null +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ForeachSyncScenario.cs @@ -0,0 +1,64 @@ +using FluentAssertions; +using System; +using System.Collections.Generic; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using WorkflowCore.Primitives; +using WorkflowCore.Testing; +using Xunit; + +namespace WorkflowCore.IntegrationTests.Scenarios +{ + public class ForeachSyncScenario : WorkflowTest + { + public class DoSomething : StepBody + { + public int Counter { get; set; } + + public override ExecutionResult Run(IStepExecutionContext context) + { + return ExecutionResult.Next(); + } + } + + public class MyDataClass + { + public int Counter { get; set; } + } + + public class ForeachSyncWorkflow : IWorkflow + { + public string Id => "ForeachSyncWorkflow"; + public int Version => 1; + public void Build(IWorkflowBuilder builder) + { + builder + .StartWith(_ => ExecutionResult.Next()) + .ForEach(x => new List() { 10, 2, 3 }, _ => false) + .Do(x => x + .StartWith() + .Input(step => step.Period, (_, context) => TimeSpan.FromSeconds((int)context.Item)) + .Then() + .Input(step => step.Counter, (data, context) => (int)context.Item) + .Output(data => data.Counter, step => step.Counter) + ); + } + } + + public ForeachSyncScenario() + { + Setup(); + } + + [Fact] + public void Scenario() + { + var workflowId = StartWorkflow(null); + WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); + + GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); + GetData(workflowId).Counter.Should().Be(3); + UnhandledStepErrors.Count.Should().Be(0); + } + } +} From 4c940a6ea78947466adb8915de18e286a7718382 Mon Sep 17 00:00:00 2001 From: Leon Segal Date: Sat, 11 Jul 2020 21:39:33 +0200 Subject: [PATCH 015/342] add Foreach support for ControlPersistenceData for backward compatibility --- src/WorkflowCore/Primitives/Foreach.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/WorkflowCore/Primitives/Foreach.cs b/src/WorkflowCore/Primitives/Foreach.cs index dd4454583..d72371e56 100644 --- a/src/WorkflowCore/Primitives/Foreach.cs +++ b/src/WorkflowCore/Primitives/Foreach.cs @@ -26,24 +26,32 @@ public override ExecutionResult Run(IStepExecutionContext context) } } - if (context.PersistenceData is IteratorPersistenceData persistanceData && persistanceData?.ChildrenActive == true) + if (context.PersistenceData is IteratorPersistenceData persistenceData && persistenceData?.ChildrenActive == true) { if (context.Workflow.IsBranchComplete(context.ExecutionPointer.Id)) { if (!RunParallel) { var values = Collection.Cast(); - persistanceData.Index++; - if (persistanceData.Index < values.Count()) + persistenceData.Index++; + if (persistenceData.Index < values.Count()) { - return ExecutionResult.Branch(new List(new object[] { values.ElementAt(persistanceData.Index) }), persistanceData); + return ExecutionResult.Branch(new List(new object[] { values.ElementAt(persistenceData.Index) }), persistenceData); } } return ExecutionResult.Next(); } - return ExecutionResult.Persist(persistanceData); + return ExecutionResult.Persist(persistenceData); + } + + if (context.PersistenceData is ControlPersistenceData controlPersistenceData && controlPersistenceData?.ChildrenActive == true) + { + if (context.Workflow.IsBranchComplete(context.ExecutionPointer.Id)) + { + return ExecutionResult.Next(); + } } return ExecutionResult.Persist(context.PersistenceData); From 3e70f58918a66e5d36b1c02662a29eccb64eff5a Mon Sep 17 00:00:00 2001 From: Andrey Borisko Date: Thu, 23 Jul 2020 16:19:49 -0400 Subject: [PATCH 016/342] #607 switched to ConcurrentHashSet. --- src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs | 7 ++++--- src/WorkflowCore/WorkflowCore.csproj | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs index 47097bcc8..54d384879 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using ConcurrentCollections; using Microsoft.Extensions.Logging; using WorkflowCore.Interface; using WorkflowCore.Models; @@ -54,7 +55,7 @@ private async void Execute() { var cancelToken = _cancellationTokenSource.Token; var activeTasks = new Dictionary(); - var secondPasses = new HashSet(); + var secondPasses = new ConcurrentHashSet(); while (!cancelToken.IsCancellationRequested) { @@ -83,7 +84,7 @@ private async void Execute() continue; } - secondPasses.Remove(item); + secondPasses.TryRemove(item); var task = new Task(async (object data) => { @@ -92,7 +93,7 @@ private async void Execute() await ExecuteItem((string)data); while (EnableSecondPasses && secondPasses.Contains(item)) { - secondPasses.Remove(item); + secondPasses.TryRemove(item); await ExecuteItem((string)data); } } diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index fca9b4de3..b4748923d 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -24,6 +24,7 @@ + From 9af7c6f2794024c61f46cf2101ca4d7d77681d6b Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 31 Jul 2020 14:59:57 -0700 Subject: [PATCH 017/342] option to auto delete complete workflows on redis --- .../ServiceCollectionExtensions.cs | 4 ++-- .../Services/RedisPersistenceProvider.cs | 8 +++++++- .../WorkflowCore.Providers.Redis.csproj | 4 ++-- .../RedisPersistenceProviderFixture.cs | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/providers/WorkflowCore.Providers.Redis/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.Redis/ServiceCollectionExtensions.cs index a517690f2..ccc96a98c 100644 --- a/src/providers/WorkflowCore.Providers.Redis/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.Redis/ServiceCollectionExtensions.cs @@ -20,9 +20,9 @@ public static WorkflowOptions UseRedisLocking(this WorkflowOptions options, stri return options; } - public static WorkflowOptions UseRedisPersistence(this WorkflowOptions options, string connectionString, string prefix) + public static WorkflowOptions UseRedisPersistence(this WorkflowOptions options, string connectionString, string prefix, bool deleteComplete = false) { - options.UsePersistence(sp => new RedisPersistenceProvider(connectionString, prefix, sp.GetService())); + options.UsePersistence(sp => new RedisPersistenceProvider(connectionString, prefix, deleteComplete, sp.GetService())); return options; } diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs index 621f01e8b..ad92848e5 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs @@ -25,14 +25,16 @@ public class RedisPersistenceProvider : IPersistenceProvider private readonly IDatabase _redis; private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; + private readonly bool _removeComplete; - public RedisPersistenceProvider(string connectionString, string prefix, ILoggerFactory logFactory) + public RedisPersistenceProvider(string connectionString, string prefix, bool removeComplete, ILoggerFactory logFactory) { _connectionString = connectionString; _prefix = prefix; _logger = logFactory.CreateLogger(GetType()); _multiplexer = ConnectionMultiplexer.Connect(_connectionString); _redis = _multiplexer.GetDatabase(); + _removeComplete = removeComplete; } public async Task CreateNewWorkflow(WorkflowInstance workflow) @@ -50,7 +52,11 @@ public async Task PersistWorkflow(WorkflowInstance workflow) if ((workflow.Status == WorkflowStatus.Runnable) && (workflow.NextExecution.HasValue)) await _redis.SortedSetAddAsync($"{_prefix}.{WORKFLOW_SET}.{RUNNABLE_INDEX}", workflow.Id, workflow.NextExecution.Value); else + { await _redis.SortedSetRemoveAsync($"{_prefix}.{WORKFLOW_SET}.{RUNNABLE_INDEX}", workflow.Id); + if (workflow.Status == WorkflowStatus.Complete) + await _redis.HashDeleteAsync($"{_prefix}.{WORKFLOW_SET}", workflow.Id); + } } public async Task> GetRunnableInstances(DateTime asAt) diff --git a/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj b/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj index 4513eb506..bdb8c6456 100644 --- a/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj +++ b/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj @@ -2,14 +2,14 @@ netstandard2.0 - 3.0.1 + 3.0.2 https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md https://github.com/danielgerlag/workflow-core.git git https://github.com/danielgerlag/workflow-core Redis providers for Workflow Core (Persistence, queueing, distributed locking and event hubs) - 3.0.1 + 3.0.2 diff --git a/test/WorkflowCore.Tests.Redis/RedisPersistenceProviderFixture.cs b/test/WorkflowCore.Tests.Redis/RedisPersistenceProviderFixture.cs index 105e5900a..cb68f7753 100644 --- a/test/WorkflowCore.Tests.Redis/RedisPersistenceProviderFixture.cs +++ b/test/WorkflowCore.Tests.Redis/RedisPersistenceProviderFixture.cs @@ -26,7 +26,7 @@ protected override IPersistenceProvider Subject { if (_subject == null) { - var client = new RedisPersistenceProvider(RedisDockerSetup.ConnectionString, "test", new LoggerFactory()); + var client = new RedisPersistenceProvider(RedisDockerSetup.ConnectionString, "test", false, new LoggerFactory()); client.EnsureStoreExists(); _subject = client; } From f7b3f8781ff15aeee93e679091fb1aa42a24fc5e Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sun, 2 Aug 2020 08:12:02 -0700 Subject: [PATCH 018/342] check flag --- .../Services/RedisPersistenceProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs index ad92848e5..79a15b970 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs @@ -54,7 +54,7 @@ public async Task PersistWorkflow(WorkflowInstance workflow) else { await _redis.SortedSetRemoveAsync($"{_prefix}.{WORKFLOW_SET}.{RUNNABLE_INDEX}", workflow.Id); - if (workflow.Status == WorkflowStatus.Complete) + if (_removeComplete && workflow.Status == WorkflowStatus.Complete) await _redis.HashDeleteAsync($"{_prefix}.{WORKFLOW_SET}", workflow.Id); } } From 15b5dc3fa40aa22225d991e9e16472f26d7ba5fb Mon Sep 17 00:00:00 2001 From: kirsanium Date: Sat, 11 Jul 2020 02:29:50 +0700 Subject: [PATCH 019/342] add possibility to not use `WorkflowBuilder.StartWith()` every time --- src/WorkflowCore/Interface/IStepBuilder.cs | 140 +--------------- .../Interface/IWorkflowBuilder.cs | 2 +- .../Interface/IWorkflowModifier.cs | 149 ++++++++++++++++++ .../FluentBuilders/WorkflowBuilder.cs | 97 +++++++++++- 4 files changed, 246 insertions(+), 142 deletions(-) create mode 100644 src/WorkflowCore/Interface/IWorkflowModifier.cs diff --git a/src/WorkflowCore/Interface/IStepBuilder.cs b/src/WorkflowCore/Interface/IStepBuilder.cs index d5ebcec7b..c654a9d20 100644 --- a/src/WorkflowCore/Interface/IStepBuilder.cs +++ b/src/WorkflowCore/Interface/IStepBuilder.cs @@ -6,7 +6,7 @@ namespace WorkflowCore.Interface { - public interface IStepBuilder + public interface IStepBuilder : IWorkflowModifier where TStepBody : IStepBody { @@ -28,36 +28,6 @@ public interface IStepBuilder /// IStepBuilder Id(string id); - /// - /// Specify the next step in the workflow - /// - /// The type of the step to execute - /// Configure additional parameters for this step - /// - IStepBuilder Then(Action> stepSetup = null) where TStep : IStepBody; - - /// - /// Specify the next step in the workflow - /// - /// - /// - /// - IStepBuilder Then(IStepBuilder newStep) where TStep : IStepBody; - - /// - /// Specify an inline next step in the workflow - /// - /// - /// - IStepBuilder Then(Func body); - - /// - /// Specify an inline next step in the workflow - /// - /// - /// - IStepBuilder Then(Action body); - /// /// Specify the next step in the workflow by Id /// @@ -129,26 +99,6 @@ public interface IStepBuilder /// IStepBuilder Output(Action action); - /// - /// Wait here until to specified event is published - /// - /// The name used to identify the kind of event to wait for - /// A specific key value within the context of the event to wait for - /// Listen for events as of this effective date - /// A conditon that when true will cancel this WaitFor - /// - IStepBuilder WaitFor(string eventName, Expression> eventKey, Expression> effectiveDate = null, Expression> cancelCondition = null); - - /// - /// Wait here until to specified event is published - /// - /// The name used to identify the kind of event to wait for - /// A specific key value within the context of the event to wait for - /// Listen for events as of this effective date - /// A conditon that when true will cancel this WaitFor - /// - IStepBuilder WaitFor(string eventName, Expression> eventKey, Expression> effectiveDate = null, Expression> cancelCondition = null); - IStepBuilder End(string name) where TStep : IStepBody; /// @@ -165,83 +115,6 @@ public interface IStepBuilder /// IStepBuilder EndWorkflow(); - /// - /// Wait for a specified period - /// - /// - /// - IStepBuilder Delay(Expression> period); - - /// - /// Evaluate an expression and take a different path depending on the value - /// - /// Expression to evaluate for decision - /// - IStepBuilder Decide(Expression> expression); - - /// - /// Execute a block of steps, once for each item in a collection in a parallel foreach - /// - /// Resolves a collection for iterate over - /// - IContainerStepBuilder ForEach(Expression> collection); - - /// - /// Execute a block of steps, once for each item in a collection in a RunParallel foreach - /// - /// Resolves a collection for iterate over - /// - IContainerStepBuilder ForEach(Expression> collection, Expression> runParallel); - - /// - /// Repeat a block of steps until a condition becomes true - /// - /// Resolves a condition to break out of the while loop - /// - IContainerStepBuilder While(Expression> condition); - - /// - /// Execute a block of steps if a condition is true - /// - /// Resolves a condition to evaluate - /// - IContainerStepBuilder If(Expression> condition); - - /// - /// Configure an outcome for this step, then wire it to a sequence - /// - /// - /// - IContainerStepBuilder When(Expression> outcomeValue, string label = null); - - /// - /// Execute multiple blocks of steps in parallel - /// - /// - IParallelStepBuilder Parallel(); - - /// - /// Execute a sequence of steps in a container - /// - /// - IStepBuilder Saga(Action> builder); - - /// - /// Schedule a block of steps to execute in parallel sometime in the future - /// - /// The time span to wait before executing the block - /// - IContainerStepBuilder Schedule(Expression> time); - - /// - /// Schedule a block of steps to execute in parallel sometime in the future at a recurring interval - /// - /// The time span to wait between recurring executions - /// Resolves a condition to stop the recurring task - /// - IContainerStepBuilder Recur(Expression> interval, Expression> until); - - /// /// Undo step if unhandled exception is thrown by this step /// @@ -277,16 +150,5 @@ public interface IStepBuilder /// /// IStepBuilder CancelCondition(Expression> cancelCondition, bool proceedAfterCancel = false); - - /// - /// Wait here until an external activity is complete - /// - /// The name used to identify the activity to wait for - /// The data to pass the external activity worker - /// Listen for events as of this effective date - /// A conditon that when true will cancel this WaitFor - /// - IStepBuilder Activity(string activityName, Expression> parameters = null, Expression> effectiveDate = null, Expression> cancelCondition = null); - } } diff --git a/src/WorkflowCore/Interface/IWorkflowBuilder.cs b/src/WorkflowCore/Interface/IWorkflowBuilder.cs index 404a359f3..ec7b7bad2 100644 --- a/src/WorkflowCore/Interface/IWorkflowBuilder.cs +++ b/src/WorkflowCore/Interface/IWorkflowBuilder.cs @@ -20,7 +20,7 @@ public interface IWorkflowBuilder void AttachBranch(IWorkflowBuilder branch); } - public interface IWorkflowBuilder : IWorkflowBuilder + public interface IWorkflowBuilder : IWorkflowBuilder, IWorkflowModifier { IStepBuilder StartWith(Action> stepSetup = null) where TStep : IStepBody; diff --git a/src/WorkflowCore/Interface/IWorkflowModifier.cs b/src/WorkflowCore/Interface/IWorkflowModifier.cs new file mode 100644 index 000000000..963e17af6 --- /dev/null +++ b/src/WorkflowCore/Interface/IWorkflowModifier.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections; +using System.Linq.Expressions; +using WorkflowCore.Models; +using WorkflowCore.Primitives; + +namespace WorkflowCore.Interface +{ + public interface IWorkflowModifier + where TStepBody : IStepBody + + { + /// + /// Specify the next step in the workflow + /// + /// The type of the step to execute + /// Configure additional parameters for this step + /// + IStepBuilder Then(Action> stepSetup = null) where TStep : IStepBody; + + /// + /// Specify the next step in the workflow + /// + /// + /// + /// + IStepBuilder Then(IStepBuilder newStep) where TStep : IStepBody; + + /// + /// Specify an inline next step in the workflow + /// + /// + /// + IStepBuilder Then(Func body); + + /// + /// Specify an inline next step in the workflow + /// + /// + /// + IStepBuilder Then(Action body); + + /// + /// Wait here until to specified event is published + /// + /// The name used to identify the kind of event to wait for + /// A specific key value within the context of the event to wait for + /// Listen for events as of this effective date + /// A conditon that when true will cancel this WaitFor + /// + IStepBuilder WaitFor(string eventName, Expression> eventKey, + Expression> effectiveDate = null, Expression> cancelCondition = null); + + /// + /// Wait here until to specified event is published + /// + /// The name used to identify the kind of event to wait for + /// A specific key value within the context of the event to wait for + /// Listen for events as of this effective date + /// A conditon that when true will cancel this WaitFor + /// + IStepBuilder WaitFor(string eventName, + Expression> eventKey, + Expression> effectiveDate = null, Expression> cancelCondition = null); + + /// + /// Wait for a specified period + /// + /// + /// + IStepBuilder Delay(Expression> period); + + /// + /// Evaluate an expression and take a different path depending on the value + /// + /// Expression to evaluate for decision + /// + IStepBuilder Decide(Expression> expression); + + /// + /// Execute a block of steps, once for each item in a collection in a parallel foreach + /// + /// Resolves a collection for iterate over + /// + IContainerStepBuilder ForEach(Expression> collection); + + /// + /// Repeat a block of steps until a condition becomes true + /// + /// Resolves a condition to break out of the while loop + /// + IContainerStepBuilder While(Expression> condition); + + /// + /// Execute a block of steps if a condition is true + /// + /// Resolves a condition to evaluate + /// + IContainerStepBuilder If(Expression> condition); + + /// + /// Configure an outcome for this step, then wire it to a sequence + /// + /// + /// + IContainerStepBuilder When(Expression> outcomeValue, + string label = null); + + /// + /// Execute multiple blocks of steps in parallel + /// + /// + IParallelStepBuilder Parallel(); + + /// + /// Execute a sequence of steps in a container + /// + /// + IStepBuilder Saga(Action> builder); + + /// + /// Schedule a block of steps to execute in parallel sometime in the future + /// + /// The time span to wait before executing the block + /// + IContainerStepBuilder Schedule(Expression> time); + + /// + /// Schedule a block of steps to execute in parallel sometime in the future at a recurring interval + /// + /// The time span to wait between recurring executions + /// Resolves a condition to stop the recurring task + /// + IContainerStepBuilder Recur(Expression> interval, + Expression> until); + + /// + /// Wait here until an external activity is complete + /// + /// The name used to identify the activity to wait for + /// The data to pass the external activity worker + /// Listen for events as of this effective date + /// A conditon that when true will cancel this WaitFor + /// + IStepBuilder Activity(string activityName, Expression> parameters = null, + Expression> effectiveDate = null, Expression> cancelCondition = null); + + } +} \ No newline at end of file diff --git a/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs b/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs index 2621f80d3..e5c7faef3 100644 --- a/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs +++ b/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs @@ -1,6 +1,8 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Primitives; @@ -148,7 +150,98 @@ public IWorkflowBuilder CreateBranch() var result = new WorkflowBuilder(new List()); return result; } - + + public IStepBuilder Then(Action> stepSetup = null) where TStep : IStepBody + { + return Start().Then(stepSetup); + } + + public IStepBuilder Then(IStepBuilder newStep) where TStep : IStepBody + { + return Start().Then(newStep); + } + + public IStepBuilder Then(Func body) + { + return Start().Then(body); + } + + public IStepBuilder Then(Action body) + { + return Start().Then(body); + } + + public IStepBuilder WaitFor(string eventName, Expression> eventKey, Expression> effectiveDate = null, + Expression> cancelCondition = null) + { + return Start().WaitFor(eventName, eventKey, effectiveDate, cancelCondition); + } + + public IStepBuilder WaitFor(string eventName, Expression> eventKey, Expression> effectiveDate = null, + Expression> cancelCondition = null) + { + return Start().WaitFor(eventName, eventKey, effectiveDate, cancelCondition); + } + + public IStepBuilder Delay(Expression> period) + { + return Start().Delay(period); + } + + public IStepBuilder Decide(Expression> expression) + { + return Start().Decide(expression); + } + + public IContainerStepBuilder ForEach(Expression> collection) + { + return Start().ForEach(collection); + } + + public IContainerStepBuilder While(Expression> condition) + { + return Start().While(condition); + } + + public IContainerStepBuilder If(Expression> condition) + { + return Start().If(condition); + } + + public IContainerStepBuilder When(Expression> outcomeValue, string label = null) + { + return ((IWorkflowModifier) Start()).When(outcomeValue, label); + } + + public IParallelStepBuilder Parallel() + { + return Start().Parallel(); + } + + public IStepBuilder Saga(Action> builder) + { + return Start().Saga(builder); + } + + public IContainerStepBuilder Schedule(Expression> time) + { + return Start().Schedule(time); + } + + public IContainerStepBuilder Recur(Expression> interval, Expression> until) + { + return Start().Recur(interval, until); + } + + public IStepBuilder Activity(string activityName, Expression> parameters = null, Expression> effectiveDate = null, + Expression> cancelCondition = null) + { + return Start().Activity(activityName, parameters, effectiveDate, cancelCondition); + } + + private IStepBuilder Start() + { + return StartWith(_ => ExecutionResult.Next()); + } } - } From 28035febbae6316049eadc588e67b8c646297f05 Mon Sep 17 00:00:00 2001 From: kirsanium Date: Mon, 3 Aug 2020 06:58:53 +0700 Subject: [PATCH 020/342] fix conflicts --- src/WorkflowCore/Interface/IWorkflowModifier.cs | 7 +++++++ .../Services/FluentBuilders/WorkflowBuilder.cs | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/src/WorkflowCore/Interface/IWorkflowModifier.cs b/src/WorkflowCore/Interface/IWorkflowModifier.cs index 963e17af6..d8af82616 100644 --- a/src/WorkflowCore/Interface/IWorkflowModifier.cs +++ b/src/WorkflowCore/Interface/IWorkflowModifier.cs @@ -83,6 +83,13 @@ IStepBuilder WaitFor(string eventName, /// Resolves a collection for iterate over /// IContainerStepBuilder ForEach(Expression> collection); + + /// + /// Execute a block of steps, once for each item in a collection in a RunParallel foreach + /// + /// Resolves a collection for iterate over + /// + IContainerStepBuilder ForEach(Expression> collection, Expression> runParallel); /// /// Repeat a block of steps until a condition becomes true diff --git a/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs b/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs index e5c7faef3..0013118a7 100644 --- a/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs +++ b/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs @@ -197,6 +197,11 @@ public IContainerStepBuilder ForEach(Expression ForEach(Expression> collection, Expression> runParallel) + { + return Start().ForEach(collection, runParallel); + } public IContainerStepBuilder While(Expression> condition) { From c7f8d8c8ad1eb672e1de6435f54fb84893da91d1 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 8 Aug 2020 08:16:37 -0700 Subject: [PATCH 021/342] remove object pooling --- WorkflowCore.sln | 9 ++- src/WorkflowCore/Models/WorkflowOptions.cs | 2 +- .../BackgroundTasks/WorkflowConsumer.cs | 70 ++++++++----------- test/ScratchPad/Program.cs | 36 +++++++--- test/ScratchPad/ScratchPad.csproj | 10 +-- 5 files changed, 73 insertions(+), 54 deletions(-) diff --git a/WorkflowCore.sln b/WorkflowCore.sln index 81030f058..5134c23dc 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -141,7 +141,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.DSL", "src\Wor EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample18", "src\samples\WorkflowCore.Sample18\WorkflowCore.Sample18.csproj", "{5BE6D628-B9DB-4C76-AAEB-8F3800509A84}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Sample09s", "src\samples\WorkflowCore.Sample09s\WorkflowCore.Sample09s.csproj", "{E32CF21A-29CC-46D1-8044-FCC327F2B281}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample09s", "src\samples\WorkflowCore.Sample09s\WorkflowCore.Sample09s.csproj", "{E32CF21A-29CC-46D1-8044-FCC327F2B281}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScratchPad", "test\ScratchPad\ScratchPad.csproj", "{51BB7DCD-01DD-453D-A1E7-17E5E3DBB14C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -349,6 +351,10 @@ Global {E32CF21A-29CC-46D1-8044-FCC327F2B281}.Debug|Any CPU.Build.0 = Debug|Any CPU {E32CF21A-29CC-46D1-8044-FCC327F2B281}.Release|Any CPU.ActiveCfg = Release|Any CPU {E32CF21A-29CC-46D1-8044-FCC327F2B281}.Release|Any CPU.Build.0 = Release|Any CPU + {51BB7DCD-01DD-453D-A1E7-17E5E3DBB14C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51BB7DCD-01DD-453D-A1E7-17E5E3DBB14C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {51BB7DCD-01DD-453D-A1E7-17E5E3DBB14C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {51BB7DCD-01DD-453D-A1E7-17E5E3DBB14C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -407,6 +413,7 @@ Global {20B98905-08CB-4854-8E2C-A31A078383E9} = {EF47161E-E399-451C-BDE8-E92AAD3BD761} {5BE6D628-B9DB-4C76-AAEB-8F3800509A84} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} {E32CF21A-29CC-46D1-8044-FCC327F2B281} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} + {51BB7DCD-01DD-453D-A1E7-17E5E3DBB14C} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC0FA8D3-6449-4FDA-BB46-ECF58FAD23B4} diff --git a/src/WorkflowCore/Models/WorkflowOptions.cs b/src/WorkflowCore/Models/WorkflowOptions.cs index 635223af5..44f1f1375 100644 --- a/src/WorkflowCore/Models/WorkflowOptions.cs +++ b/src/WorkflowCore/Models/WorkflowOptions.cs @@ -16,7 +16,7 @@ public class WorkflowOptions internal TimeSpan PollInterval; internal TimeSpan IdleTime; internal TimeSpan ErrorRetryInterval; - internal int MaxConcurrentWorkflows = Math.Max(Environment.ProcessorCount, 2); + internal int MaxConcurrentWorkflows = Math.Max(Environment.ProcessorCount, 4); public IServiceCollection Services { get; private set; } diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index f9222c715..b21c7ec72 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -12,17 +12,17 @@ internal class WorkflowConsumer : QueueConsumer, IBackgroundTask { private readonly IDistributedLockProvider _lockProvider; private readonly IDateTimeProvider _datetimeProvider; - private readonly ObjectPool _persistenceStorePool; - private readonly ObjectPool _executorPool; + private readonly IPersistenceProvider _persistenceStore; + private readonly IWorkflowExecutor _executor; protected override int MaxConcurrentItems => Options.MaxConcurrentWorkflows; protected override QueueType Queue => QueueType.Workflow; - public WorkflowConsumer(IPooledObjectPolicy persistencePoolPolicy, IQueueProvider queueProvider, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowRegistry registry, IDistributedLockProvider lockProvider, IPooledObjectPolicy executorPoolPolicy, IDateTimeProvider datetimeProvider, WorkflowOptions options) + public WorkflowConsumer(IPersistenceProvider persistenceProvider, IQueueProvider queueProvider, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowRegistry registry, IDistributedLockProvider lockProvider, IWorkflowExecutor executor, IDateTimeProvider datetimeProvider, WorkflowOptions options) : base(queueProvider, loggerFactory, options) { - _persistenceStorePool = new DefaultObjectPool(persistencePoolPolicy); - _executorPool = new DefaultObjectPool(executorPoolPolicy); + _persistenceStore = persistenceProvider; + _executor = executor; _lockProvider = lockProvider; _datetimeProvider = datetimeProvider; } @@ -37,53 +37,45 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance WorkflowInstance workflow = null; WorkflowExecutorResult result = null; - var persistenceStore = _persistenceStorePool.Get(); + try { - try - { - cancellationToken.ThrowIfCancellationRequested(); - workflow = await persistenceStore.GetWorkflowInstance(itemId); - if (workflow.Status == WorkflowStatus.Runnable) + cancellationToken.ThrowIfCancellationRequested(); + workflow = await _persistenceStore.GetWorkflowInstance(itemId); + if (workflow.Status == WorkflowStatus.Runnable) + { + try + { + result = await _executor.Execute(workflow); + } + finally { - var executor = _executorPool.Get(); - try - { - result = await executor.Execute(workflow); - } - finally - { - _executorPool.Return(executor); - await persistenceStore.PersistWorkflow(workflow); - await QueueProvider.QueueWork(itemId, QueueType.Index); - } + await _persistenceStore.PersistWorkflow(workflow); + await QueueProvider.QueueWork(itemId, QueueType.Index); } } - finally + } + finally + { + await _lockProvider.ReleaseLock(itemId); + if ((workflow != null) && (result != null)) { - await _lockProvider.ReleaseLock(itemId); - if ((workflow != null) && (result != null)) + foreach (var sub in result.Subscriptions) { - foreach (var sub in result.Subscriptions) - { - await SubscribeEvent(sub, persistenceStore); - } + await SubscribeEvent(sub, _persistenceStore); + } - await persistenceStore.PersistErrors(result.Errors); + await _persistenceStore.PersistErrors(result.Errors); - var readAheadTicks = _datetimeProvider.UtcNow.Add(Options.PollInterval).Ticks; + var readAheadTicks = _datetimeProvider.UtcNow.Add(Options.PollInterval).Ticks; - if ((workflow.Status == WorkflowStatus.Runnable) && workflow.NextExecution.HasValue && workflow.NextExecution.Value < readAheadTicks) - { - new Task(() => FutureQueue(workflow, cancellationToken)).Start(); - } + if ((workflow.Status == WorkflowStatus.Runnable) && workflow.NextExecution.HasValue && workflow.NextExecution.Value < readAheadTicks) + { + new Task(() => FutureQueue(workflow, cancellationToken)).Start(); } } } - finally - { - _persistenceStorePool.Return(persistenceStore); - } + } private async Task SubscribeEvent(EventSubscription subscription, IPersistenceProvider persistenceStore) diff --git a/test/ScratchPad/Program.cs b/test/ScratchPad/Program.cs index 40c569a29..08f383712 100644 --- a/test/ScratchPad/Program.cs +++ b/test/ScratchPad/Program.cs @@ -26,15 +26,30 @@ public static void Main(string[] args) //loader.LoadDefinition(Properties.Resources.HelloWorld, Deserializers.Json); host.Start(); - - host.StartWorkflow("Test01", 1, new WfData() + + var ids = new List(); + //for (var i = 0; i < 12000; i++) + //{ + // var wid = host.StartWorkflow("Test01", 1, new WfData() { Value1 = "two", Value2 = "data2" }).Result; + // ids.Add(wid); + //} + //Console.WriteLine("started..."); + //Thread.Sleep(5000); + + host.PublishEvent("MyEvent", "Key", "one", DateTime.Now); + + for (var i = 0; i < 12000; i++) { - Value1 = "two", - Value2 = "data2" - }); + var wid = host.StartWorkflow("Test01", 1, new WfData() { Value1 = "two", Value2 = "data2" }).Result; + ids.Add(wid); + } + + Console.WriteLine("started2..."); + Thread.Sleep(5000); + + host.PublishEvent("MyEvent", "Key", "one", DateTime.Now); + - - Console.ReadLine(); host.Stop(); } @@ -46,8 +61,11 @@ private static IServiceProvider ConfigureServices() services.AddLogging(); //services.AddWorkflow(); //services.AddWorkflow(x => x.UseMongoDB(@"mongodb://localhost:27017", "workflow")); + services.AddWorkflow(cfg => { + cfg.UseSqlServer(@"Server=.;Database=WorkflowCore;Trusted_Connection=True;", true, true); + cfg.UseMaxConcurrentWorkflows(100); //var ddbConfig = new AmazonDynamoDBConfig() { RegionEndpoint = RegionEndpoint.USWest2 }; //cfg.UseAwsDynamoPersistence(new EnvironmentVariablesAWSCredentials(), ddbConfig, "elastic"); //cfg.UseElasticsearch(new ConnectionSettings(new Uri("http://localhost:9200")), "workflows"); @@ -111,10 +129,12 @@ public void Build(IWorkflowBuilder builder) builder .StartWith() + .WaitFor("MyEvent", (data, context) => "Key", data => DateTime.Now) + .Output(data => data.Value1, step => step.EventData) .Then((context) => { Console.WriteLine("------1"); - Task.Delay(TimeSpan.FromSeconds(20)).Wait(); + Task.Delay(TimeSpan.FromSeconds(5)).Wait(); Console.WriteLine("------2"); return ExecutionResult.Next(); }) diff --git a/test/ScratchPad/ScratchPad.csproj b/test/ScratchPad/ScratchPad.csproj index 548b8fa61..4fb61dd24 100644 --- a/test/ScratchPad/ScratchPad.csproj +++ b/test/ScratchPad/ScratchPad.csproj @@ -10,6 +10,11 @@ false + + + + + @@ -23,11 +28,6 @@ - - - - - True From ffca3da9d045520529f517b450ef910df7265500 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 8 Aug 2020 08:17:55 -0700 Subject: [PATCH 022/342] bump version --- src/WorkflowCore/WorkflowCore.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index b4748923d..9554b92f9 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,9 +15,9 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.1.6 - 3.1.6.0 - 3.1.6.0 + 3.2.0 + 3.2.0.0 + 3.2.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png 3.1.6 From 2127e6fa45cc191d0c2de363eb7c7673f8c8a476 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 8 Aug 2020 08:44:05 -0700 Subject: [PATCH 023/342] shutdown concurrency issue --- .../Services/BackgroundTasks/QueueConsumer.cs | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs index 54d384879..0d1a5474a 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs @@ -61,7 +61,12 @@ private async void Execute() { try { - if (activeTasks.Count >= MaxConcurrentItems) + var activeCount = 0; + lock (activeTasks) + { + activeCount = activeTasks.Count; + } + if (activeCount >= MaxConcurrentItems) { await Task.Delay(Options.IdleTime); continue; @@ -75,14 +80,19 @@ private async void Execute() await Task.Delay(Options.IdleTime, cancelToken); continue; } - - if (activeTasks.ContainsKey(item)) + + var hasTask = false; + lock (activeTasks) + { + hasTask = activeTasks.ContainsKey(item); + } + if (hasTask) { secondPasses.Add(item); if (!EnableSecondPasses) await QueueProvider.QueueWork(item, Queue); continue; - } + } secondPasses.TryRemove(item); @@ -121,7 +131,13 @@ private async void Execute() } } - foreach (var task in activeTasks.Values) + List toComplete; + lock (activeTasks) + { + toComplete = activeTasks.Values.ToList(); + } + + foreach (var task in toComplete) task.Wait(); } From f8121321a88b8ca0a212bc064eff73b8d4b9b431 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 8 Aug 2020 08:53:28 -0700 Subject: [PATCH 024/342] package version --- src/WorkflowCore/WorkflowCore.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 9554b92f9..0b8e610f8 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -20,7 +20,7 @@ 3.2.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.1.6 + 3.2.0 From 0b50ab7956ef95c1aeec419244d9b4733e9975e5 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 8 Aug 2020 19:57:02 -0700 Subject: [PATCH 025/342] performance tweaks for event bursts --- src/WorkflowCore/Interface/IGreyList.cs | 9 +++ .../ServiceCollectionExtensions.cs | 1 + .../Services/BackgroundTasks/EventConsumer.cs | 13 +++- .../BackgroundTasks/RunnablePoller.cs | 19 +++++- .../BackgroundTasks/WorkflowConsumer.cs | 7 ++- src/WorkflowCore/Services/GreyList.cs | 63 +++++++++++++++++++ src/WorkflowCore/WorkflowCore.csproj | 8 +-- 7 files changed, 109 insertions(+), 11 deletions(-) create mode 100644 src/WorkflowCore/Interface/IGreyList.cs create mode 100644 src/WorkflowCore/Services/GreyList.cs diff --git a/src/WorkflowCore/Interface/IGreyList.cs b/src/WorkflowCore/Interface/IGreyList.cs new file mode 100644 index 000000000..3d2e0093a --- /dev/null +++ b/src/WorkflowCore/Interface/IGreyList.cs @@ -0,0 +1,9 @@ +namespace WorkflowCore.Interface +{ + public interface IGreyList + { + void Add(string id); + void Remove(string id); + bool Contains(string id); + } +} \ No newline at end of file diff --git a/src/WorkflowCore/ServiceCollectionExtensions.cs b/src/WorkflowCore/ServiceCollectionExtensions.cs index c241107c2..6fe511845 100644 --- a/src/WorkflowCore/ServiceCollectionExtensions.cs +++ b/src/WorkflowCore/ServiceCollectionExtensions.cs @@ -48,6 +48,7 @@ public static IServiceCollection AddWorkflow(this IServiceCollection services, A services.AddTransient(); services.AddTransient(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs index 06682431a..bdd730fca 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs @@ -16,13 +16,15 @@ internal class EventConsumer : QueueConsumer, IBackgroundTask private readonly IEventRepository _eventRepository; private readonly IDistributedLockProvider _lockProvider; private readonly IDateTimeProvider _datetimeProvider; + private readonly IGreyList _greylist; protected override int MaxConcurrentItems => 2; protected override QueueType Queue => QueueType.Event; - public EventConsumer(IWorkflowRepository workflowRepository, ISubscriptionRepository subscriptionRepository, IEventRepository eventRepository, IQueueProvider queueProvider, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowRegistry registry, IDistributedLockProvider lockProvider, WorkflowOptions options, IDateTimeProvider datetimeProvider) + public EventConsumer(IWorkflowRepository workflowRepository, ISubscriptionRepository subscriptionRepository, IEventRepository eventRepository, IQueueProvider queueProvider, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowRegistry registry, IDistributedLockProvider lockProvider, WorkflowOptions options, IDateTimeProvider datetimeProvider, IGreyList greylist) : base(queueProvider, loggerFactory, options) { _workflowRepository = workflowRepository; + _greylist = greylist; _subscriptionRepository = subscriptionRepository; _eventRepository = eventRepository; _lockProvider = lockProvider; @@ -41,6 +43,11 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance { cancellationToken.ThrowIfCancellationRequested(); var evt = await _eventRepository.GetEvent(itemId); + if (evt.IsProcessed) + { + _greylist.Add($"evt:{evt.Id}"); + return; + } if (evt.EventTime <= _datetimeProvider.UtcNow) { IEnumerable subs = null; @@ -60,7 +67,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance subs = await _subscriptionRepository.GetSubscriptions(evt.EventName, evt.EventKey, evt.EventTime); } - var toQueue = new List(); + var toQueue = new HashSet(); var complete = true; foreach (var sub in subs.ToList()) @@ -79,7 +86,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance } } - private async Task SeedSubscription(Event evt, EventSubscription sub, List toQueue, CancellationToken cancellationToken) + private async Task SeedSubscription(Event evt, EventSubscription sub, HashSet toQueue, CancellationToken cancellationToken) { foreach (var eventId in await _eventRepository.GetEvents(sub.EventName, sub.EventKey, sub.SubscribeAsOf)) { diff --git a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs index 559c123f0..0800fe582 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs @@ -13,12 +13,14 @@ internal class RunnablePoller : IBackgroundTask private readonly IDistributedLockProvider _lockProvider; private readonly IQueueProvider _queueProvider; private readonly ILogger _logger; + private readonly IGreyList _greylist; private readonly WorkflowOptions _options; private Timer _pollTimer; - public RunnablePoller(IPersistenceProvider persistenceStore, IQueueProvider queueProvider, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowRegistry registry, IDistributedLockProvider lockProvider, WorkflowOptions options) + public RunnablePoller(IPersistenceProvider persistenceStore, IQueueProvider queueProvider, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowRegistry registry, IDistributedLockProvider lockProvider, IGreyList greylist, WorkflowOptions options) { _persistenceStore = persistenceStore; + _greylist = greylist; _queueProvider = queueProvider; _logger = loggerFactory.CreateLogger(); _lockProvider = lockProvider; @@ -55,7 +57,13 @@ private async void PollRunnables(object target) var runnables = await _persistenceStore.GetRunnableInstances(DateTime.Now); foreach (var item in runnables) { + if (_greylist.Contains($"wf:{item}")) + { + _logger.LogDebug($"Got greylisted workflow {item}"); + continue; + } _logger.LogDebug("Got runnable instance {0}", item); + _greylist.Add($"wf:{item}"); await _queueProvider.QueueWork(item, QueueType.Workflow); } } @@ -80,8 +88,15 @@ private async void PollRunnables(object target) var events = await _persistenceStore.GetRunnableEvents(DateTime.Now); foreach (var item in events.ToList()) { + if (_greylist.Contains($"evt:{item}")) + { + _logger.LogDebug($"Got greylisted event {item}"); + _greylist.Add($"evt:{item}"); + continue; + } _logger.LogDebug($"Got unprocessed event {item}"); - await _queueProvider.QueueWork(item, QueueType.Event); + _greylist.Add($"evt:{item}"); + await _queueProvider.QueueWork(item, QueueType.Event); } } finally diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index b21c7ec72..5742270ce 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -14,14 +14,16 @@ internal class WorkflowConsumer : QueueConsumer, IBackgroundTask private readonly IDateTimeProvider _datetimeProvider; private readonly IPersistenceProvider _persistenceStore; private readonly IWorkflowExecutor _executor; + private readonly IGreyList _greylist; protected override int MaxConcurrentItems => Options.MaxConcurrentWorkflows; protected override QueueType Queue => QueueType.Workflow; - public WorkflowConsumer(IPersistenceProvider persistenceProvider, IQueueProvider queueProvider, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowRegistry registry, IDistributedLockProvider lockProvider, IWorkflowExecutor executor, IDateTimeProvider datetimeProvider, WorkflowOptions options) + public WorkflowConsumer(IPersistenceProvider persistenceProvider, IQueueProvider queueProvider, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowRegistry registry, IDistributedLockProvider lockProvider, IWorkflowExecutor executor, IDateTimeProvider datetimeProvider, IGreyList greylist, WorkflowOptions options) : base(queueProvider, loggerFactory, options) { _persistenceStore = persistenceProvider; + _greylist = greylist; _executor = executor; _lockProvider = lockProvider; _datetimeProvider = datetimeProvider; @@ -43,7 +45,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance cancellationToken.ThrowIfCancellationRequested(); workflow = await _persistenceStore.GetWorkflowInstance(itemId); if (workflow.Status == WorkflowStatus.Runnable) - { + { try { result = await _executor.Execute(workflow); @@ -52,6 +54,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance { await _persistenceStore.PersistWorkflow(workflow); await QueueProvider.QueueWork(itemId, QueueType.Index); + _greylist.Remove($"wf:{itemId}"); } } } diff --git a/src/WorkflowCore/Services/GreyList.cs b/src/WorkflowCore/Services/GreyList.cs new file mode 100644 index 000000000..a697e2958 --- /dev/null +++ b/src/WorkflowCore/Services/GreyList.cs @@ -0,0 +1,63 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Concurrent; +using System.Threading; +using WorkflowCore.Interface; + +namespace WorkflowCore.Services +{ + public class GreyList : IGreyList, IDisposable + { + private readonly Timer _cycleTimer; + private readonly ConcurrentDictionary _list; + private readonly ILogger _logger; + private const int CYCLE_TIME = 600; + + public GreyList(ILoggerFactory loggerFactory) + { + _logger = loggerFactory.CreateLogger(); + _list = new ConcurrentDictionary(); + _cycleTimer = new Timer(new TimerCallback(Cycle), null, TimeSpan.FromSeconds(CYCLE_TIME), TimeSpan.FromSeconds(CYCLE_TIME)); + } + + public void Add(string id) + { + _list.AddOrUpdate(id, DateTime.Now, (key, val) => DateTime.Now); + } + + public bool Contains(string id) + { + if (!_list.TryGetValue(id, out var start)) + return false; + + var result = start > (DateTime.Now.AddMinutes(-2)); + + if (!result) + _list.TryRemove(id, out var _); + + return result; + } + + private void Cycle(object target) + { + try + { + _list.Clear(); + } + catch (Exception ex) + { + _logger.LogError(ex, ex.Message); + } + } + + public void Dispose() + { + _cycleTimer.Dispose(); + } + + public void Remove(string id) + { + _list.TryRemove(id, out var _); + } + } +} diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 0b8e610f8..96d7bbeb3 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.2.0 - 3.2.0.0 - 3.2.0.0 + 3.2.1 + 3.2.1.0 + 3.2.1.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.2.0 + 3.2.1 From 906a7d779ec85e9249e6ccd0e7fdb4009001d1af Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sun, 9 Aug 2020 08:53:08 -0700 Subject: [PATCH 026/342] tweaks --- src/WorkflowCore/Services/GreyList.cs | 7 ++++--- src/WorkflowCore/WorkflowCore.csproj | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/WorkflowCore/Services/GreyList.cs b/src/WorkflowCore/Services/GreyList.cs index a697e2958..ec1148291 100644 --- a/src/WorkflowCore/Services/GreyList.cs +++ b/src/WorkflowCore/Services/GreyList.cs @@ -11,13 +11,14 @@ public class GreyList : IGreyList, IDisposable private readonly Timer _cycleTimer; private readonly ConcurrentDictionary _list; private readonly ILogger _logger; - private const int CYCLE_TIME = 600; + private const int CYCLE_TIME = 30; + private const int TTL = 5; public GreyList(ILoggerFactory loggerFactory) { _logger = loggerFactory.CreateLogger(); _list = new ConcurrentDictionary(); - _cycleTimer = new Timer(new TimerCallback(Cycle), null, TimeSpan.FromSeconds(CYCLE_TIME), TimeSpan.FromSeconds(CYCLE_TIME)); + _cycleTimer = new Timer(new TimerCallback(Cycle), null, TimeSpan.FromMinutes(CYCLE_TIME), TimeSpan.FromMinutes(CYCLE_TIME)); } public void Add(string id) @@ -30,7 +31,7 @@ public bool Contains(string id) if (!_list.TryGetValue(id, out var start)) return false; - var result = start > (DateTime.Now.AddMinutes(-2)); + var result = start > (DateTime.Now.AddMinutes(-1 * TTL)); if (!result) _list.TryRemove(id, out var _); diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 96d7bbeb3..ae35416de 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.2.1 - 3.2.1.0 - 3.2.1.0 + 3.2.2 + 3.2.2.0 + 3.2.2.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.2.1 + 3.2.2 From 8d37f4ceeef228d5fb4df98ac81b7f8b44a230a4 Mon Sep 17 00:00:00 2001 From: Pavlo Korobov Date: Fri, 14 Aug 2020 21:34:39 +0200 Subject: [PATCH 027/342] Make IScopeProvider.cs aware of IStepExecutionContext --- src/WorkflowCore/Interface/IScopeProvider.cs | 2 +- src/WorkflowCore/Services/ScopeProvider.cs | 12 +++---- src/WorkflowCore/Services/WorkflowExecutor.cs | 20 +++++------ .../WorkflowCore.TestAssets.csproj | 2 +- .../Services/ScopeProviderTests.cs | 36 +++++++++++++++++++ .../Services/WorkflowExecutorFixture.cs | 7 +--- 6 files changed, 55 insertions(+), 24 deletions(-) create mode 100644 test/WorkflowCore.UnitTests/Services/ScopeProviderTests.cs diff --git a/src/WorkflowCore/Interface/IScopeProvider.cs b/src/WorkflowCore/Interface/IScopeProvider.cs index c69351731..bab5f94d2 100644 --- a/src/WorkflowCore/Interface/IScopeProvider.cs +++ b/src/WorkflowCore/Interface/IScopeProvider.cs @@ -12,6 +12,6 @@ public interface IScopeProvider /// Create a new service scope /// /// - IServiceScope CreateScope(); + IServiceScope CreateScope(IStepExecutionContext context); } } \ No newline at end of file diff --git a/src/WorkflowCore/Services/ScopeProvider.cs b/src/WorkflowCore/Services/ScopeProvider.cs index ad1ae98d2..5c52d8eb9 100644 --- a/src/WorkflowCore/Services/ScopeProvider.cs +++ b/src/WorkflowCore/Services/ScopeProvider.cs @@ -6,20 +6,20 @@ namespace WorkflowCore.Services { /// /// A concrete implementation for the IScopeProvider interface - /// Largely to get around the problems of unit testing an extension method (CreateScope()) + /// Could be used for context-aware scope creation customization /// public class ScopeProvider : IScopeProvider { - private readonly IServiceProvider provider; + private readonly IServiceScopeFactory _serviceScopeFactory; - public ScopeProvider(IServiceProvider provider) + public ScopeProvider(IServiceScopeFactory serviceScopeFactory) { - this.provider = provider; + _serviceScopeFactory = serviceScopeFactory; } - public IServiceScope CreateScope() + public IServiceScope CreateScope(IStepExecutionContext context) { - return provider.CreateScope(); + return _serviceScopeFactory.CreateScope(); } } } diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index 7597e7490..8d5507bae 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -137,7 +137,16 @@ private bool InitializeStep(WorkflowInstance workflow, WorkflowStep step, Workfl private async Task ExecuteStep(WorkflowInstance workflow, WorkflowStep step, ExecutionPointer pointer, WorkflowExecutorResult wfResult, WorkflowDefinition def) { - using (var scope = _scopeProvider.CreateScope()) + IStepExecutionContext context = new StepExecutionContext() + { + Workflow = workflow, + Step = step, + PersistenceData = pointer.PersistenceData, + ExecutionPointer = pointer, + Item = pointer.ContextItem + }; + + using (var scope = _scopeProvider.CreateScope(context)) { _logger.LogDebug("Starting step {0} on workflow {1}", step.Name, workflow.Id); @@ -157,15 +166,6 @@ private async Task ExecuteStep(WorkflowInstance workflow, WorkflowStep step, Exe return; } - IStepExecutionContext context = new StepExecutionContext() - { - Workflow = workflow, - Step = step, - PersistenceData = pointer.PersistenceData, - ExecutionPointer = pointer, - Item = pointer.ContextItem - }; - foreach (var input in step.Inputs) input.AssignInput(workflow.Data, body, context); diff --git a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj index 0105a6e9d..88cd82ea7 100644 --- a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj +++ b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj @@ -36,7 +36,7 @@ - + diff --git a/test/WorkflowCore.UnitTests/Services/ScopeProviderTests.cs b/test/WorkflowCore.UnitTests/Services/ScopeProviderTests.cs new file mode 100644 index 000000000..ab7869d1d --- /dev/null +++ b/test/WorkflowCore.UnitTests/Services/ScopeProviderTests.cs @@ -0,0 +1,36 @@ +using System; +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using WorkflowCore.Interface; +using WorkflowCore.Services; +using Xunit; + +namespace WorkflowCore.UnitTests.Services +{ + public class ScopeProviderTests + { + private readonly ScopeProvider _sut; + private readonly Mock _scopeFactoryMock; + + public ScopeProviderTests() + { + _scopeFactoryMock = new Mock(); + + _sut = new ScopeProvider(_scopeFactoryMock.Object); + } + + [Fact(DisplayName = "Should return IServiceScope")] + public void ReturnsServiceScope_CreateScopeCalled() + { + var scope = new Mock().Object; + _scopeFactoryMock.Setup(x => x.CreateScope()) + .Returns(scope); + + var result = _sut.CreateScope(new Mock().Object); + + result.Should().NotBeNull().And.BeSameAs(scope); + _scopeFactoryMock.Verify(x => x.CreateScope(), Times.Once); + } + } +} \ No newline at end of file diff --git a/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs b/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs index 6c99586f6..622af03ff 100644 --- a/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs +++ b/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs @@ -3,15 +3,10 @@ using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Services; -using FluentAssertions; using Xunit; -using WorkflowCore.Primitives; -using System.Linq.Expressions; -using System.Threading.Tasks; namespace WorkflowCore.UnitTests.Services { @@ -44,7 +39,7 @@ public WorkflowExecutorFixture() Options = new WorkflowOptions(A.Fake()); var scope = A.Fake(); - A.CallTo(() => ScopeProvider.CreateScope()).Returns(scope); + A.CallTo(() => ScopeProvider.CreateScope(A._)).Returns(scope); A.CallTo(() => scope.ServiceProvider).Returns(ServiceProvider); A.CallTo(() => DateTimeProvider.Now).Returns(DateTime.Now); From 486a7b6722e36a88b8e3913eb4576a61d0e6015c Mon Sep 17 00:00:00 2001 From: Pavlo Korobov Date: Fri, 14 Aug 2020 22:07:29 +0200 Subject: [PATCH 028/342] Make IScopeProvider.cs aware of IStepExecutionContext --- test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj index 88cd82ea7..12da1f57b 100644 --- a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj +++ b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj @@ -36,7 +36,7 @@ - + From 8f0c2deab73fc14be5500b7d0734ad18033ec67b Mon Sep 17 00:00:00 2001 From: Alexander Kulik Date: Sun, 6 Sep 2020 12:34:29 +0300 Subject: [PATCH 029/342] Pass the CancellationToken into IStepExecutionContext for async steps. --- src/WorkflowCore/Interface/IStepExecutionContext.cs | 7 +++++-- src/WorkflowCore/Interface/IWorkflowExecutor.cs | 5 +++-- src/WorkflowCore/Models/StepExecutionContext.cs | 3 +++ .../Services/BackgroundTasks/WorkflowConsumer.cs | 2 +- src/WorkflowCore/Services/WorkflowExecutor.cs | 10 ++++++---- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/WorkflowCore/Interface/IStepExecutionContext.cs b/src/WorkflowCore/Interface/IStepExecutionContext.cs index e59198a13..7aab7123c 100644 --- a/src/WorkflowCore/Interface/IStepExecutionContext.cs +++ b/src/WorkflowCore/Interface/IStepExecutionContext.cs @@ -1,4 +1,5 @@ -using WorkflowCore.Models; +using System.Threading; +using WorkflowCore.Models; namespace WorkflowCore.Interface { @@ -12,6 +13,8 @@ public interface IStepExecutionContext WorkflowStep Step { get; set; } - WorkflowInstance Workflow { get; set; } + WorkflowInstance Workflow { get; set; } + + CancellationToken CancellationToken { get; set; } } } \ No newline at end of file diff --git a/src/WorkflowCore/Interface/IWorkflowExecutor.cs b/src/WorkflowCore/Interface/IWorkflowExecutor.cs index 798057fdc..d0df49d40 100644 --- a/src/WorkflowCore/Interface/IWorkflowExecutor.cs +++ b/src/WorkflowCore/Interface/IWorkflowExecutor.cs @@ -1,10 +1,11 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; using WorkflowCore.Models; namespace WorkflowCore.Interface { public interface IWorkflowExecutor { - Task Execute(WorkflowInstance workflow); + Task Execute(WorkflowInstance workflow, CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/src/WorkflowCore/Models/StepExecutionContext.cs b/src/WorkflowCore/Models/StepExecutionContext.cs index b48bcd35c..096d719f3 100644 --- a/src/WorkflowCore/Models/StepExecutionContext.cs +++ b/src/WorkflowCore/Models/StepExecutionContext.cs @@ -1,4 +1,5 @@ using WorkflowCore.Interface; +using System.Threading; namespace WorkflowCore.Models { @@ -13,5 +14,7 @@ public class StepExecutionContext : IStepExecutionContext public object PersistenceData { get; set; } public object Item { get; set; } + + public CancellationToken CancellationToken { get; set; } = CancellationToken.None; } } diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index 5742270ce..6ce3776b5 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -48,7 +48,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance { try { - result = await _executor.Execute(workflow); + result = await _executor.Execute(workflow, cancellationToken); } finally { diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index 8d5507bae..e557a2bb2 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.Interface; @@ -37,7 +38,7 @@ public WorkflowExecutor(IWorkflowRegistry registry, IServiceProvider serviceProv _executionResultProcessor = executionResultProcessor; } - public async Task Execute(WorkflowInstance workflow) + public async Task Execute(WorkflowInstance workflow, CancellationToken cancellationToken = default) { var wfResult = new WorkflowExecutorResult(); @@ -76,7 +77,7 @@ public async Task Execute(WorkflowInstance workflow) if (!InitializeStep(workflow, step, wfResult, def, pointer)) continue; - await ExecuteStep(workflow, step, pointer, wfResult, def); + await ExecuteStep(workflow, step, pointer, wfResult, def, cancellationToken); } catch (Exception ex) { @@ -135,7 +136,7 @@ private bool InitializeStep(WorkflowInstance workflow, WorkflowStep step, Workfl return true; } - private async Task ExecuteStep(WorkflowInstance workflow, WorkflowStep step, ExecutionPointer pointer, WorkflowExecutorResult wfResult, WorkflowDefinition def) + private async Task ExecuteStep(WorkflowInstance workflow, WorkflowStep step, ExecutionPointer pointer, WorkflowExecutorResult wfResult, WorkflowDefinition def, CancellationToken cancellationToken = default) { IStepExecutionContext context = new StepExecutionContext() { @@ -143,7 +144,8 @@ private async Task ExecuteStep(WorkflowInstance workflow, WorkflowStep step, Exe Step = step, PersistenceData = pointer.PersistenceData, ExecutionPointer = pointer, - Item = pointer.ContextItem + Item = pointer.ContextItem, + CancellationToken = cancellationToken }; using (var scope = _scopeProvider.CreateScope(context)) From 9732cc4c94bddae85b4566dd772fea7944aca101 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Mon, 7 Sep 2020 12:31:55 -0700 Subject: [PATCH 030/342] issue #635 --- .../FluentBuilders/WorkflowBuilder.cs | 28 +++++++++++++++++++ src/WorkflowCore/WorkflowCore.csproj | 8 +++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs b/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs index 0013118a7..f5acd7694 100644 --- a/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs +++ b/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs @@ -65,6 +65,28 @@ public void AttachBranch(IWorkflowBuilder branch) if (Branches.Contains(branch)) return; + var branchStart = LastStep + branch.LastStep + 1; + + foreach (var step in branch.Steps) + { + var oldId = step.Id; + step.Id = oldId + branchStart; + foreach (var step2 in branch.Steps) + { + foreach (var outcome in step2.Outcomes) + { + if (outcome.NextStep == oldId) + outcome.NextStep = step.Id; + } + + for (var i = 0; i < step2.Children.Count; i++) + { + if (step2.Children[i] == oldId) + step2.Children[i] = step.Id; + } + } + } + foreach (var step in branch.Steps) { var oldId = step.Id; @@ -76,6 +98,12 @@ public void AttachBranch(IWorkflowBuilder branch) if (outcome.NextStep == oldId) outcome.NextStep = step.Id; } + + for (var i = 0; i < step2.Children.Count; i++) + { + if (step2.Children[i] == oldId) + step2.Children[i] = step.Id; + } } } diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index ae35416de..68e457261 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.2.2 - 3.2.2.0 - 3.2.2.0 + 3.2.3 + 3.2.3.0 + 3.2.3.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.2.2 + 3.2.3 From 18be33b9b204301e2118d1d811d049c744f1f4b3 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sun, 13 Sep 2020 19:47:20 -0700 Subject: [PATCH 031/342] async issue --- .../Services/BackgroundTasks/QueueConsumer.cs | 6 ++++-- src/WorkflowCore/WorkflowCore.csproj | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs index 0d1a5474a..69c146644 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs @@ -141,11 +141,11 @@ private async void Execute() task.Wait(); } - private async Task ExecuteItem(string itemId) + private Task ExecuteItem(string itemId) { try { - await ProcessItem(itemId, _cancellationTokenSource.Token); + ProcessItem(itemId, _cancellationTokenSource.Token).Wait(); } catch (OperationCanceledException) { @@ -155,6 +155,8 @@ private async Task ExecuteItem(string itemId) { Logger.LogError(default(EventId), ex, $"Error executing item {itemId} - {ex.Message}"); } + + return Task.CompletedTask; } } } diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 68e457261..b1e8c48df 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.2.3 - 3.2.3.0 - 3.2.3.0 + 3.2.4 + 3.2.4.0 + 3.2.4.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.2.3 + 3.2.4 From b8af93ab05213dbd3e9973d919594d26f75c0889 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 16 Sep 2020 07:40:42 -0700 Subject: [PATCH 032/342] issue #645 --- .../Services/BackgroundTasks/QueueConsumer.cs | 86 +++++++++---------- src/WorkflowCore/WorkflowCore.csproj | 8 +- 2 files changed, 44 insertions(+), 50 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs index 69c146644..b1bb7c5b9 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs @@ -21,12 +21,17 @@ internal abstract class QueueConsumer : IBackgroundTask protected readonly WorkflowOptions Options; protected Task DispatchTask; private CancellationTokenSource _cancellationTokenSource; + private Dictionary _activeTasks; + private ConcurrentHashSet _secondPasses; protected QueueConsumer(IQueueProvider queueProvider, ILoggerFactory loggerFactory, WorkflowOptions options) { QueueProvider = queueProvider; Options = options; Logger = loggerFactory.CreateLogger(GetType()); + + _activeTasks = new Dictionary(); + _secondPasses = new ConcurrentHashSet(); } protected abstract Task ProcessItem(string itemId, CancellationToken cancellationToken); @@ -39,9 +44,8 @@ public virtual void Start() } _cancellationTokenSource = new CancellationTokenSource(); - - DispatchTask = new Task(Execute, TaskCreationOptions.LongRunning); - DispatchTask.Start(); + + DispatchTask = Task.Factory.StartNew(Execute, TaskCreationOptions.LongRunning); } public virtual void Stop() @@ -51,20 +55,18 @@ public virtual void Stop() DispatchTask = null; } - private async void Execute() + private async Task Execute() { - var cancelToken = _cancellationTokenSource.Token; - var activeTasks = new Dictionary(); - var secondPasses = new ConcurrentHashSet(); + var cancelToken = _cancellationTokenSource.Token; while (!cancelToken.IsCancellationRequested) { try { var activeCount = 0; - lock (activeTasks) + lock (_activeTasks) { - activeCount = activeTasks.Count; + activeCount = _activeTasks.Count; } if (activeCount >= MaxConcurrentItems) { @@ -82,45 +84,26 @@ private async void Execute() } var hasTask = false; - lock (activeTasks) + lock (_activeTasks) { - hasTask = activeTasks.ContainsKey(item); + hasTask = _activeTasks.ContainsKey(item); } if (hasTask) { - secondPasses.Add(item); + _secondPasses.Add(item); if (!EnableSecondPasses) await QueueProvider.QueueWork(item, Queue); continue; } - secondPasses.TryRemove(item); + _secondPasses.TryRemove(item); - var task = new Task(async (object data) => - { - try - { - await ExecuteItem((string)data); - while (EnableSecondPasses && secondPasses.Contains(item)) - { - secondPasses.TryRemove(item); - await ExecuteItem((string)data); - } - } - finally - { - lock (activeTasks) - { - activeTasks.Remove((string)data); - } - } - }, item); - lock (activeTasks) + var waitHandle = new ManualResetEvent(false); + lock (_activeTasks) { - activeTasks.Add(item, task); + _activeTasks.Add(item, waitHandle); } - - task.Start(); + var task = ExecuteItem(item, waitHandle); } catch (OperationCanceledException) { @@ -131,21 +114,26 @@ private async void Execute() } } - List toComplete; - lock (activeTasks) + List toComplete; + lock (_activeTasks) { - toComplete = activeTasks.Values.ToList(); + toComplete = _activeTasks.Values.ToList(); } - - foreach (var task in toComplete) - task.Wait(); + + foreach (var handle in toComplete) + handle.WaitOne(); } - private Task ExecuteItem(string itemId) + private async Task ExecuteItem(string itemId, EventWaitHandle waitHandle) { try { - ProcessItem(itemId, _cancellationTokenSource.Token).Wait(); + await ProcessItem(itemId, _cancellationTokenSource.Token); + while (EnableSecondPasses && _secondPasses.Contains(itemId)) + { + _secondPasses.TryRemove(itemId); + await ProcessItem(itemId, _cancellationTokenSource.Token); + } } catch (OperationCanceledException) { @@ -155,8 +143,14 @@ private Task ExecuteItem(string itemId) { Logger.LogError(default(EventId), ex, $"Error executing item {itemId} - {ex.Message}"); } - - return Task.CompletedTask; + finally + { + waitHandle.Set(); + lock (_activeTasks) + { + _activeTasks.Remove(itemId); + } + } } } } diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index b1e8c48df..d3a447a9f 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.2.4 - 3.2.4.0 - 3.2.4.0 + 3.2.5 + 3.2.5.0 + 3.2.5.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.2.4 + 3.2.5 From b80fc13b0f4e691089476af5a541c19e57fcab5f Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 19 Sep 2020 17:09:06 -0700 Subject: [PATCH 033/342] Cosmos DB support (#649) --- README.md | 1 + docs/persistence.md | 1 + .../Interface/ICosmosDbProvisioner.cs | 9 + .../Models/PersistedEvent.cs | 50 +++++ .../Models/PersistedSubscription.cs | 70 +++++++ .../Models/PersistedWorkflow.cs | 75 +++++++ .../WorkflowCore.Providers.Azure/README.md | 2 + .../ServiceCollectionExtensions.cs | 8 + .../Services/CosmosDbPersistenceProvider.cs | 195 ++++++++++++++++++ .../Services/CosmosDbProvisioner.cs | 38 ++++ .../WorkflowCore.Providers.Azure.csproj | 10 +- 11 files changed, 455 insertions(+), 4 deletions(-) create mode 100644 src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbProvisioner.cs create mode 100644 src/providers/WorkflowCore.Providers.Azure/Models/PersistedEvent.cs create mode 100644 src/providers/WorkflowCore.Providers.Azure/Models/PersistedSubscription.cs create mode 100644 src/providers/WorkflowCore.Providers.Azure/Models/PersistedWorkflow.cs create mode 100644 src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs create mode 100644 src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs diff --git a/README.md b/README.md index 9c55cc475..53ef98486 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,7 @@ There are several persistence providers available as separate Nuget packages. * MemoryPersistenceProvider *(Default provider, for demo and testing purposes)* * [MongoDB](src/providers/WorkflowCore.Persistence.MongoDB) +* [Cosmos DB](src/providers/WorkflowCore.Providers.Azure) * [Amazon DynamoDB](src/providers/WorkflowCore.Providers.AWS) * [SQL Server](src/providers/WorkflowCore.Persistence.SqlServer) * [PostgreSQL](src/providers/WorkflowCore.Persistence.PostgreSQL) diff --git a/docs/persistence.md b/docs/persistence.md index 81a880c63..8a7fe55fd 100644 --- a/docs/persistence.md +++ b/docs/persistence.md @@ -9,4 +9,5 @@ There are several persistence providers available as separate Nuget packages. * [PostgreSQL](https://github.com/danielgerlag/workflow-core/tree/master/src/providers/WorkflowCore.Persistence.PostgreSQL) * [Sqlite](https://github.com/danielgerlag/workflow-core/tree/master/src/providers/WorkflowCore.Persistence.Sqlite) * [Amazon DynamoDB](https://github.com/danielgerlag/workflow-core/tree/master/src/providers/WorkflowCore.Providers.AWS) +* [Cosmos DB](https://github.com/danielgerlag/workflow-core/tree/master/src/providers/WorkflowCore.Providers.Azure) * [Redis](https://github.com/danielgerlag/workflow-core/tree/master/src/providers/WorkflowCore.Providers.Redis) diff --git a/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbProvisioner.cs b/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbProvisioner.cs new file mode 100644 index 000000000..67a738971 --- /dev/null +++ b/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbProvisioner.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace WorkflowCore.Providers.Azure.Interface +{ + public interface ICosmosDbProvisioner + { + Task Provision(string dbId); + } +} \ No newline at end of file diff --git a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedEvent.cs b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedEvent.cs new file mode 100644 index 000000000..341f7b71b --- /dev/null +++ b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedEvent.cs @@ -0,0 +1,50 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using WorkflowCore.Models; + +namespace WorkflowCore.Providers.Azure.Models +{ + public class PersistedEvent + { + public string id { get; set; } + + public string EventName { get; set; } + + public string EventKey { get; set; } + + public string EventData { get; set; } + + public DateTime EventTime { get; set; } + + public bool IsProcessed { get; set; } + + private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; + + public static PersistedEvent FromInstance(Event instance) + { + return new PersistedEvent() + { + id = instance.Id, + EventKey = instance.EventKey, + EventName = instance.EventName, + EventTime = instance.EventTime, + IsProcessed = instance.IsProcessed, + EventData = JsonConvert.SerializeObject(instance.EventData, SerializerSettings), + }; + } + + public static Event ToInstance(PersistedEvent instance) + { + return new Event() + { + Id = instance.id, + EventKey = instance.EventKey, + EventName = instance.EventName, + EventTime = instance.EventTime, + IsProcessed = instance.IsProcessed, + EventData = JsonConvert.DeserializeObject(instance.EventData, SerializerSettings), + }; + } + } +} diff --git a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedSubscription.cs b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedSubscription.cs new file mode 100644 index 000000000..d0660046c --- /dev/null +++ b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedSubscription.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json; +using WorkflowCore.Models; + +namespace WorkflowCore.Providers.Azure.Models +{ + public class PersistedSubscription + { + public string id { get; set; } + + public string WorkflowId { get; set; } + + public int StepId { get; set; } + + public string ExecutionPointerId { get; set; } + + public string EventName { get; set; } + + public string EventKey { get; set; } + + public DateTime SubscribeAsOf { get; set; } + + public string SubscriptionData { get; set; } + + public string ExternalToken { get; set; } + + public string ExternalWorkerId { get; set; } + + public DateTime? ExternalTokenExpiry { get; set; } + + private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; + + public static PersistedSubscription FromInstance(EventSubscription instance) + { + return new PersistedSubscription() + { + id = instance.Id, + EventKey = instance.EventKey, + EventName = instance.EventName, + ExecutionPointerId = instance.ExecutionPointerId, + ExternalToken = instance.ExternalToken, + ExternalTokenExpiry = instance.ExternalTokenExpiry, + ExternalWorkerId = instance.ExternalWorkerId, + StepId = instance.StepId, + SubscribeAsOf = instance.SubscribeAsOf, + WorkflowId = instance.WorkflowId, + SubscriptionData = JsonConvert.SerializeObject(instance.SubscriptionData, SerializerSettings), + }; + } + + public static EventSubscription ToInstance(PersistedSubscription instance) + { + return new EventSubscription() + { + Id = instance.id, + EventKey = instance.EventKey, + EventName = instance.EventName, + ExecutionPointerId = instance.ExecutionPointerId, + ExternalToken = instance.ExternalToken, + ExternalTokenExpiry = instance.ExternalTokenExpiry, + ExternalWorkerId = instance.ExternalWorkerId, + StepId = instance.StepId, + SubscribeAsOf = instance.SubscribeAsOf, + WorkflowId = instance.WorkflowId, + SubscriptionData = JsonConvert.DeserializeObject(instance.SubscriptionData, SerializerSettings), + }; + } + } +} diff --git a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedWorkflow.cs b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedWorkflow.cs new file mode 100644 index 000000000..c9f565592 --- /dev/null +++ b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedWorkflow.cs @@ -0,0 +1,75 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using WorkflowCore.Models; + +namespace WorkflowCore.Providers.Azure.Models +{ + public class PersistedWorkflow + { + public string id { get; set; } + + public string WorkflowDefinitionId { get; set; } + + public int Version { get; set; } + + public string Description { get; set; } + + public string Reference { get; set; } + + public string ExecutionPointers { get; set; } + + public long? NextExecution { get; set; } + + public WorkflowStatus Status { get; set; } + + public string Data { get; set; } + + public DateTime CreateTime { get; set; } + + public DateTime? CompleteTime { get; set; } + + private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; + + public static PersistedWorkflow FromInstance(WorkflowInstance instance) + { + var result = new PersistedWorkflow() + { + id = instance.Id, + CompleteTime = instance.CompleteTime, + CreateTime = instance.CreateTime, + Description = instance.Description, + NextExecution = instance.NextExecution, + Reference = instance.Reference, + Status = instance.Status, + Version = instance.Version, + WorkflowDefinitionId = instance.WorkflowDefinitionId, + Data = JsonConvert.SerializeObject(instance.Data, SerializerSettings), + ExecutionPointers = JsonConvert.SerializeObject(instance.ExecutionPointers, SerializerSettings), + }; + + return result; + } + + public static WorkflowInstance ToInstance(PersistedWorkflow instance) + { + var result = new WorkflowInstance() + { + Id = instance.id, + CompleteTime = instance.CompleteTime, + CreateTime = instance.CreateTime, + Description = instance.Description, + NextExecution = instance.NextExecution, + Reference = instance.Reference, + Status = instance.Status, + Version = instance.Version, + WorkflowDefinitionId = instance.WorkflowDefinitionId, + Data = JsonConvert.DeserializeObject(instance.Data, SerializerSettings), + ExecutionPointers = JsonConvert.DeserializeObject(instance.ExecutionPointers, SerializerSettings), + }; + + return result; + } + + } +} diff --git a/src/providers/WorkflowCore.Providers.Azure/README.md b/src/providers/WorkflowCore.Providers.Azure/README.md index a6641c564..10c17bfbe 100644 --- a/src/providers/WorkflowCore.Providers.Azure/README.md +++ b/src/providers/WorkflowCore.Providers.Azure/README.md @@ -3,6 +3,7 @@ * Provides [DLM](https://en.wikipedia.org/wiki/Distributed_lock_manager) support on [Workflow Core](../../README.md) using Azure Blob Storage leases. * Provides Queueing support on [Workflow Core](../../README.md) using Azure Storage queues. * Provides event hub support on [Workflow Core](../../README.md) backed by Azure Service Bus. +* Provides persistence on [Workflow Core](../../README.md) backed by Azure Cosmos DB. This makes it possible to have a cluster of nodes processing your workflows. @@ -30,5 +31,6 @@ services.AddWorkflow(options => { options.UseAzureSynchronization("azure storage connection string"); options.UseAzureServiceBusEventHub("service bus connection string", "topic name", "subscription name"); + options.UseCosmosDbPersistence("connection string"); }); ``` \ No newline at end of file diff --git a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs index 5abb111fc..9129e4de5 100644 --- a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Logging; using WorkflowCore.Models; +using WorkflowCore.Providers.Azure.Interface; using WorkflowCore.Providers.Azure.Services; namespace Microsoft.Extensions.DependencyInjection @@ -24,5 +25,12 @@ public static WorkflowOptions UseAzureServiceBusEventHub( return options; } + + public static WorkflowOptions UseCosmosDbPersistence(this WorkflowOptions options, string connectionString, string databaseId) + { + options.Services.AddTransient(sp => new CosmosDbProvisioner(connectionString, sp.GetService())); + options.UsePersistence(sp => new CosmosDbPersistenceProvider(connectionString, databaseId, sp.GetService())); + return options; + } } } diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs new file mode 100644 index 000000000..8ca697fc2 --- /dev/null +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Azure.Cosmos; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using WorkflowCore.Providers.Azure.Interface; +using WorkflowCore.Providers.Azure.Models; + +namespace WorkflowCore.Providers.Azure.Services +{ + public class CosmosDbPersistenceProvider : IPersistenceProvider + { + + public const string WorkflowContainerName = "workflows"; + public const string EventContainerName = "events"; + public const string SubscriptionContainerName = "subscriptions"; + + private ICosmosDbProvisioner _provisioner; + private string _dbId; + private CosmosClient _client; + private Lazy _workflowContainer; + private Lazy _eventContainer; + private Lazy _subscriptionContainer; + + public CosmosDbPersistenceProvider(string connectionString, string dbId, ICosmosDbProvisioner provisioner) + { + _provisioner = provisioner; + _dbId = dbId; + _client = new CosmosClient(connectionString); + _workflowContainer = new Lazy(() => _client.GetDatabase(_dbId).GetContainer(WorkflowContainerName)); + _eventContainer = new Lazy(() => _client.GetDatabase(_dbId).GetContainer(EventContainerName)); + _subscriptionContainer = new Lazy(() => _client.GetDatabase(_dbId).GetContainer(SubscriptionContainerName)); + } + + public async Task ClearSubscriptionToken(string eventSubscriptionId, string token) + { + var existing = await _subscriptionContainer.Value.ReadItemAsync(eventSubscriptionId, new PartitionKey(eventSubscriptionId)); + + if (existing.Resource.ExternalToken != token) + throw new InvalidOperationException(); + existing.Resource.ExternalToken = null; + existing.Resource.ExternalWorkerId = null; + existing.Resource.ExternalTokenExpiry = null; + + await _subscriptionContainer.Value.ReplaceItemAsync(existing.Resource, eventSubscriptionId); + } + + public async Task CreateEvent(Event newEvent) + { + newEvent.Id = Guid.NewGuid().ToString(); + var result = await _eventContainer.Value.CreateItemAsync(PersistedEvent.FromInstance(newEvent)); + return result.Resource.id; + } + + public async Task CreateEventSubscription(EventSubscription subscription) + { + subscription.Id = Guid.NewGuid().ToString(); + var result = await _subscriptionContainer.Value.CreateItemAsync(PersistedSubscription.FromInstance(subscription)); + return result.Resource.id; + } + + public async Task CreateNewWorkflow(WorkflowInstance workflow) + { + workflow.Id = Guid.NewGuid().ToString(); + var result = await _workflowContainer.Value.CreateItemAsync(PersistedWorkflow.FromInstance(workflow)); + return result.Resource.id; + } + + public void EnsureStoreExists() + { + _provisioner.Provision(_dbId).Wait(); + } + + public async Task GetEvent(string id) + { + var resp = await _eventContainer.Value.ReadItemAsync(id, new PartitionKey(id)); + return PersistedEvent.ToInstance(resp.Resource); + } + + public Task> GetEvents(string eventName, string eventKey, DateTime asOf) + { + var data = _eventContainer.Value.GetItemLinqQueryable(true) + .Where(x => x.EventName == eventName && x.EventKey == eventKey) + .Where(x => x.EventTime >= asOf) + .Select(x => x.id); + + return Task.FromResult(data.AsEnumerable()); + } + + public Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf) + { + var data = _subscriptionContainer.Value.GetItemLinqQueryable(true) + .FirstOrDefault(x => x.ExternalToken == null && x.EventName == eventName && x.EventKey == eventKey && x.SubscribeAsOf <= asOf); + + return Task.FromResult(PersistedSubscription.ToInstance(data)); + } + + public Task> GetRunnableEvents(DateTime asAt) + { + var data = _eventContainer.Value.GetItemLinqQueryable(true) + .Where(x => !x.IsProcessed) + .Where(x => x.EventTime <= asAt.ToUniversalTime()) + .Select(x => x.id); + + return Task.FromResult(data.AsEnumerable()); + } + + public Task> GetRunnableInstances(DateTime asAt) + { + var now = asAt.ToUniversalTime().Ticks; + + var data = _workflowContainer.Value.GetItemLinqQueryable(true) + .Where(x => x.NextExecution.HasValue && (x.NextExecution <= now) && (x.Status == WorkflowStatus.Runnable)) + .Select(x => x.id); + + return Task.FromResult(data.AsEnumerable()); + } + + public async Task GetSubscription(string eventSubscriptionId) + { + var resp = await _subscriptionContainer.Value.ReadItemAsync(eventSubscriptionId, new PartitionKey(eventSubscriptionId)); + return PersistedSubscription.ToInstance(resp.Resource); + } + + public Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf) + { + var data = _subscriptionContainer.Value.GetItemLinqQueryable(true) + .Where(x => x.EventName == eventName && x.EventKey == eventKey && x.SubscribeAsOf <= asOf) + .ToList() + .Select(x => PersistedSubscription.ToInstance(x)); + return Task.FromResult(data.AsEnumerable()); + } + + public async Task GetWorkflowInstance(string Id) + { + var result = await _workflowContainer.Value.ReadItemAsync(Id, new PartitionKey(Id)); + return PersistedWorkflow.ToInstance(result.Resource); + } + + public Task> GetWorkflowInstances(WorkflowStatus? status, string type, DateTime? createdFrom, DateTime? createdTo, int skip, int take) + { + throw new NotImplementedException(); + } + + public Task> GetWorkflowInstances(IEnumerable ids) + { + throw new NotImplementedException(); + } + + public async Task MarkEventProcessed(string id) + { + var evt = await _eventContainer.Value.ReadItemAsync(id, new PartitionKey(id)); + evt.Resource.IsProcessed = true; + await _eventContainer.Value.ReplaceItemAsync(evt.Resource, id); + } + + public async Task MarkEventUnprocessed(string id) + { + var evt = await _eventContainer.Value.ReadItemAsync(id, new PartitionKey(id)); + evt.Resource.IsProcessed = false; + await _eventContainer.Value.ReplaceItemAsync(evt.Resource, id); + } + + public Task PersistErrors(IEnumerable errors) + { + return Task.CompletedTask; + } + + public async Task PersistWorkflow(WorkflowInstance workflow) + { + await _workflowContainer.Value.UpsertItemAsync(PersistedWorkflow.FromInstance(workflow)); + } + + public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry) + { + var sub = await _subscriptionContainer.Value.ReadItemAsync(eventSubscriptionId, new PartitionKey(eventSubscriptionId)); + var existingEntity = sub.Resource; + existingEntity.ExternalToken = token; + existingEntity.ExternalWorkerId = workerId; + existingEntity.ExternalTokenExpiry = expiry; + + await _subscriptionContainer.Value.ReplaceItemAsync(existingEntity, eventSubscriptionId); + + return true; + } + + public async Task TerminateSubscription(string eventSubscriptionId) + { + await _subscriptionContainer.Value.DeleteItemAsync(eventSubscriptionId, new PartitionKey(eventSubscriptionId)); + } + } +} diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs new file mode 100644 index 000000000..001ade0a0 --- /dev/null +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.ObjectModel; +using System.Threading.Tasks; +using Microsoft.Azure.Cosmos; +using Microsoft.Extensions.Logging; +using WorkflowCore.Providers.Azure.Interface; + +namespace WorkflowCore.Providers.Azure.Services +{ + public class CosmosDbProvisioner : ICosmosDbProvisioner + { + + private CosmosClient _client; + + public CosmosDbProvisioner(string connectionString, ILoggerFactory loggerFactory) + { + _client = new CosmosClient(connectionString); + } + + public async Task Provision(string dbId) + { + var dbResp = await _client.CreateDatabaseIfNotExistsAsync(dbId); + var wfIndexPolicy = new IndexingPolicy(); + wfIndexPolicy.IncludedPaths.Add(new IncludedPath() { Path = @"/*" }); + wfIndexPolicy.ExcludedPaths.Add(new ExcludedPath() { Path = @"/ExecutionPointers/?" }); + + Task.WaitAll( + dbResp.Database.CreateContainerIfNotExistsAsync(new ContainerProperties(CosmosDbPersistenceProvider.WorkflowContainerName, @"/id") + { + IndexingPolicy = wfIndexPolicy + }), + dbResp.Database.CreateContainerIfNotExistsAsync(new ContainerProperties(CosmosDbPersistenceProvider.EventContainerName, @"/id")), + dbResp.Database.CreateContainerIfNotExistsAsync(new ContainerProperties(CosmosDbPersistenceProvider.SubscriptionContainerName, @"/id")) + ); + } + + } +} \ No newline at end of file diff --git a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj index 28a8e06f4..43013c80c 100644 --- a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj +++ b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj @@ -7,19 +7,21 @@ - Provides distributed lock management on Workflow Core - Provides Queueing support on Workflow Core workflow workflowcore dlm - 2.0.0 + 3.0.0 $(PackageTargetFallback);dnxcore50 https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git Daniel Gerlag - 2.0.0.0 - 2.0.0.0 + 3.0.0.0 + 3.0.0.0 - + + + From 090334da581f20c71cc1a964707f86e1b099fd99 Mon Sep 17 00:00:00 2001 From: Pavlo Korobov Date: Fri, 25 Sep 2020 13:39:50 +0200 Subject: [PATCH 034/342] RabbitMQProvider.cs improvements --- .../Interfaces/IRabbitMqQueueNameProvider.cs | 11 ++++++ .../ServiceCollectionExtensions.cs | 38 ++++++++++++++++++- .../DefaultRabbitMqQueueNameProvider.cs | 23 +++++++++++ .../Services/RabbitMQProvider.cs | 37 ++++++++---------- 4 files changed, 85 insertions(+), 24 deletions(-) create mode 100644 src/providers/WorkflowCore.QueueProviders.RabbitMQ/Interfaces/IRabbitMqQueueNameProvider.cs create mode 100644 src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/DefaultRabbitMqQueueNameProvider.cs diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Interfaces/IRabbitMqQueueNameProvider.cs b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Interfaces/IRabbitMqQueueNameProvider.cs new file mode 100644 index 000000000..f39d75b52 --- /dev/null +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Interfaces/IRabbitMqQueueNameProvider.cs @@ -0,0 +1,11 @@ +using System; +using System.Linq; +using WorkflowCore.Interface; + +namespace WorkflowCore.QueueProviders.RabbitMQ.Interfaces +{ + public interface IRabbitMqQueueNameProvider + { + string GetQueueName(QueueType queue); + } +} \ No newline at end of file diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/ServiceCollectionExtensions.cs index b148a0044..e3f13bdfb 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/ServiceCollectionExtensions.cs @@ -2,18 +2,52 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection.Extensions; +using WorkflowCore.Interface; using WorkflowCore.Models; +using WorkflowCore.QueueProviders.RabbitMQ.Interfaces; using WorkflowCore.QueueProviders.RabbitMQ.Services; namespace Microsoft.Extensions.DependencyInjection { + public delegate IConnection RabbitMqConnectionFactory(IServiceProvider sp, string clientProvidedName); + public static class ServiceCollectionExtensions { public static WorkflowOptions UseRabbitMQ(this WorkflowOptions options, IConnectionFactory connectionFactory) { - options.UseQueueProvider(sp => new RabbitMQProvider(connectionFactory)); + if (options == null) throw new ArgumentNullException(nameof(options)); + if (connectionFactory == null) throw new ArgumentNullException(nameof(connectionFactory)); + + return options + .UseRabbitMQ((sp, name) => connectionFactory.CreateConnection(name)); + } + + public static WorkflowOptions UseRabbitMQ(this WorkflowOptions options, + IConnectionFactory connectionFactory, + IEnumerable hostnames) + { + if (options == null) throw new ArgumentNullException(nameof(options)); + if (connectionFactory == null) throw new ArgumentNullException(nameof(connectionFactory)); + if (hostnames == null) throw new ArgumentNullException(nameof(hostnames)); + + return options + .UseRabbitMQ((sp, name) => connectionFactory.CreateConnection(hostnames.ToList(), name)); + } + + public static WorkflowOptions UseRabbitMQ(this WorkflowOptions options, RabbitMqConnectionFactory rabbitMqConnectionFactory) + { + if (options == null) throw new ArgumentNullException(nameof(options)); + if (rabbitMqConnectionFactory == null) throw new ArgumentNullException(nameof(rabbitMqConnectionFactory)); + + options.Services.AddSingleton(rabbitMqConnectionFactory); + options.Services.TryAddTransient(); + options.UseQueueProvider(RabbitMqQueueProviderFactory); + return options; } + + private static IQueueProvider RabbitMqQueueProviderFactory(IServiceProvider sp) + => new RabbitMQProvider(sp); } } diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/DefaultRabbitMqQueueNameProvider.cs b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/DefaultRabbitMqQueueNameProvider.cs new file mode 100644 index 000000000..120de752e --- /dev/null +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/DefaultRabbitMqQueueNameProvider.cs @@ -0,0 +1,23 @@ +using WorkflowCore.Interface; +using WorkflowCore.QueueProviders.RabbitMQ.Interfaces; + +namespace WorkflowCore.QueueProviders.RabbitMQ.Services +{ + public class DefaultRabbitMqQueueNameProvider : IRabbitMqQueueNameProvider + { + public string GetQueueName(QueueType queue) + { + switch (queue) + { + case QueueType.Workflow: + return "wfc.workflow_queue"; + case QueueType.Event: + return "wfc.event_queue"; + case QueueType.Index: + return "wfc.index_queue"; + default: + return null; + } + } + } +} \ No newline at end of file diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs index c28091092..0dd1c1490 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs @@ -7,23 +7,30 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.Interface; using WorkflowCore.Models; +using WorkflowCore.QueueProviders.RabbitMQ.Interfaces; namespace WorkflowCore.QueueProviders.RabbitMQ.Services { #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously public class RabbitMQProvider : IQueueProvider { - private readonly IConnectionFactory _connectionFactory; + private readonly IRabbitMqQueueNameProvider _queueNameProvider; + private readonly RabbitMqConnectionFactory _rabbitMqConnectionFactory; + private readonly IServiceProvider _serviceProvider; + private IConnection _connection = null; private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; public bool IsDequeueBlocking => false; - public RabbitMQProvider(IConnectionFactory connectionFactory) + public RabbitMQProvider(IServiceProvider serviceProvider) { - _connectionFactory = connectionFactory; + _serviceProvider = serviceProvider; + _queueNameProvider = _serviceProvider.GetRequiredService(); + _rabbitMqConnectionFactory = _serviceProvider.GetRequiredService(); } public async Task QueueWork(string id, QueueType queue) @@ -33,9 +40,9 @@ public async Task QueueWork(string id, QueueType queue) using (var channel = _connection.CreateModel()) { - channel.QueueDeclare(queue: GetQueueName(queue), durable: true, exclusive: false, autoDelete: false, arguments: null); + channel.QueueDeclare(queue: _queueNameProvider.GetQueueName(queue), durable: true, exclusive: false, autoDelete: false, arguments: null); var body = Encoding.UTF8.GetBytes(id); - channel.BasicPublish(exchange: "", routingKey: GetQueueName(queue), basicProperties: null, body: body); + channel.BasicPublish(exchange: "", routingKey: _queueNameProvider.GetQueueName(queue), basicProperties: null, body: body); } } @@ -46,7 +53,7 @@ public async Task DequeueWork(QueueType queue, CancellationToken cancell using (var channel = _connection.CreateModel()) { - channel.QueueDeclare(queue: GetQueueName(queue), + channel.QueueDeclare(queue: _queueNameProvider.GetQueueName(queue), durable: true, exclusive: false, autoDelete: false, @@ -54,7 +61,7 @@ public async Task DequeueWork(QueueType queue, CancellationToken cancell channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false); - var msg = channel.BasicGet(GetQueueName(queue), false); + var msg = channel.BasicGet(_queueNameProvider.GetQueueName(queue), false); if (msg != null) { var data = Encoding.UTF8.GetString(msg.Body); @@ -76,7 +83,7 @@ public void Dispose() public async Task Start() { - _connection = _connectionFactory.CreateConnection("Workflow-Core"); + _connection = _rabbitMqConnectionFactory(_serviceProvider, "Workflow-Core"); } public async Task Stop() @@ -88,20 +95,6 @@ public async Task Stop() } } - private string GetQueueName(QueueType queue) - { - switch (queue) - { - case QueueType.Workflow: - return "wfc.workflow_queue"; - case QueueType.Event: - return "wfc.event_queue"; - case QueueType.Index: - return "wfc.index_queue"; - } - return null; - } - } #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously } From e760e181a6c4394464c4378d2d46f38381399a3c Mon Sep 17 00:00:00 2001 From: Pavlo Korobov Date: Fri, 25 Sep 2020 13:53:25 +0200 Subject: [PATCH 035/342] QueueNameProvider tests --- WorkflowCore.sln | 7 +++++ .../DefaultRabbitMqQueueNameProviderTests.cs | 28 +++++++++++++++++++ ...wCore.Tests.QueueProviders.RabbitMQ.csproj | 21 ++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 test/WorkflowCore.Tests.QueueProviders.RabbitMQ/Tests/DefaultRabbitMqQueueNameProviderTests.cs create mode 100644 test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj diff --git a/WorkflowCore.sln b/WorkflowCore.sln index 5134c23dc..9231faa76 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -145,6 +145,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample09s", "s EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScratchPad", "test\ScratchPad\ScratchPad.csproj", "{51BB7DCD-01DD-453D-A1E7-17E5E3DBB14C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Tests.QueueProviders.RabbitMQ", "test\WorkflowCore.Tests.QueueProviders.RabbitMQ\WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj", "{54DE20BA-EBA7-4BF0-9BD9-F03766849716}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -355,6 +357,10 @@ Global {51BB7DCD-01DD-453D-A1E7-17E5E3DBB14C}.Debug|Any CPU.Build.0 = Debug|Any CPU {51BB7DCD-01DD-453D-A1E7-17E5E3DBB14C}.Release|Any CPU.ActiveCfg = Release|Any CPU {51BB7DCD-01DD-453D-A1E7-17E5E3DBB14C}.Release|Any CPU.Build.0 = Release|Any CPU + {54DE20BA-EBA7-4BF0-9BD9-F03766849716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {54DE20BA-EBA7-4BF0-9BD9-F03766849716}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54DE20BA-EBA7-4BF0-9BD9-F03766849716}.Release|Any CPU.ActiveCfg = Release|Any CPU + {54DE20BA-EBA7-4BF0-9BD9-F03766849716}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -414,6 +420,7 @@ Global {5BE6D628-B9DB-4C76-AAEB-8F3800509A84} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} {E32CF21A-29CC-46D1-8044-FCC327F2B281} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} {51BB7DCD-01DD-453D-A1E7-17E5E3DBB14C} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} + {54DE20BA-EBA7-4BF0-9BD9-F03766849716} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC0FA8D3-6449-4FDA-BB46-ECF58FAD23B4} diff --git a/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/Tests/DefaultRabbitMqQueueNameProviderTests.cs b/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/Tests/DefaultRabbitMqQueueNameProviderTests.cs new file mode 100644 index 000000000..66bd39233 --- /dev/null +++ b/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/Tests/DefaultRabbitMqQueueNameProviderTests.cs @@ -0,0 +1,28 @@ +using FluentAssertions; +using WorkflowCore.Interface; +using WorkflowCore.QueueProviders.RabbitMQ.Services; +using Xunit; + +namespace WorkflowCore.Tests.QueueProviders.RabbitMQ.Tests +{ + public class DefaultRabbitMqQueueNameProviderTests + { + private readonly DefaultRabbitMqQueueNameProvider _sut; + + public DefaultRabbitMqQueueNameProviderTests() + { + _sut = new DefaultRabbitMqQueueNameProvider(); + } + + [Theory] + [InlineData(QueueType.Event, "wfc.event_queue")] + [InlineData(QueueType.Index, "wfc.index_queue")] + [InlineData(QueueType.Workflow, "wfc.workflow_queue")] + public void GetQueueName_ValidInput_ReturnsValidQueueName(QueueType queueType, string queueName) + { + var result = _sut.GetQueueName(queueType); + + result.Should().Be(queueName); + } + } +} \ No newline at end of file diff --git a/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj b/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj new file mode 100644 index 000000000..7ccd35c02 --- /dev/null +++ b/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp3.1 + + false + + + + + + + + + + + + + + + From d56579abbcebf30a6083a2623b02fc7bda9e72df Mon Sep 17 00:00:00 2001 From: Pavlo Korobov Date: Mon, 5 Oct 2020 13:41:58 +0200 Subject: [PATCH 036/342] Fix suggestions --- .../ServiceCollectionExtensions.cs | 6 ++++-- .../Services/RabbitMQProvider.cs | 8 +++++--- .../WorkflowCore.QueueProviders.RabbitMQ.csproj | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/ServiceCollectionExtensions.cs index e3f13bdfb..4474e403a 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/ServiceCollectionExtensions.cs @@ -41,13 +41,15 @@ public static WorkflowOptions UseRabbitMQ(this WorkflowOptions options, RabbitMq if (rabbitMqConnectionFactory == null) throw new ArgumentNullException(nameof(rabbitMqConnectionFactory)); options.Services.AddSingleton(rabbitMqConnectionFactory); - options.Services.TryAddTransient(); + options.Services.TryAddSingleton(); options.UseQueueProvider(RabbitMqQueueProviderFactory); return options; } private static IQueueProvider RabbitMqQueueProviderFactory(IServiceProvider sp) - => new RabbitMQProvider(sp); + => new RabbitMQProvider(sp, + sp.GetRequiredService(), + sp.GetRequiredService()); } } diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs index 0dd1c1490..d9ec3bbeb 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs @@ -26,11 +26,13 @@ public class RabbitMQProvider : IQueueProvider public bool IsDequeueBlocking => false; - public RabbitMQProvider(IServiceProvider serviceProvider) + public RabbitMQProvider(IServiceProvider serviceProvider, + IRabbitMqQueueNameProvider queueNameProvider, + RabbitMqConnectionFactory connectionFactory) { _serviceProvider = serviceProvider; - _queueNameProvider = _serviceProvider.GetRequiredService(); - _rabbitMqConnectionFactory = _serviceProvider.GetRequiredService(); + _queueNameProvider = queueNameProvider; + _rabbitMqConnectionFactory = connectionFactory; } public async Task QueueWork(string id, QueueType queue) diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj index 6735f21eb..025e83913 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj @@ -19,6 +19,7 @@ Queue provider for Workflow-core using RabbitMQ 2.0.0.0 2.0.0.0 + 2.1.0 From e11f6962a1ab6616d5f48ecce1a650187331473e Mon Sep 17 00:00:00 2001 From: ioanadumitru Date: Tue, 6 Oct 2020 18:00:42 +0300 Subject: [PATCH 037/342] Update WorkflowRegistry.cs Changed registry collection to a thread safe collection. --- src/WorkflowCore/Services/WorkflowRegistry.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/WorkflowCore/Services/WorkflowRegistry.cs b/src/WorkflowCore/Services/WorkflowRegistry.cs index 5677d434d..c09189a1c 100644 --- a/src/WorkflowCore/Services/WorkflowRegistry.cs +++ b/src/WorkflowCore/Services/WorkflowRegistry.cs @@ -1,4 +1,5 @@ -using System; +using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.DependencyInjection; @@ -10,7 +11,7 @@ namespace WorkflowCore.Services public class WorkflowRegistry : IWorkflowRegistry { private readonly IServiceProvider _serviceProvider; - private readonly List> _registry = new List>(); + private readonly BlockingCollection> _registry = new BlockingCollection>(); public WorkflowRegistry(IServiceProvider serviceProvider) { @@ -35,10 +36,10 @@ public WorkflowDefinition GetDefinition(string workflowId, int? version = null) public void DeregisterWorkflow(string workflowId, int version) { - var definition = _registry.Find(x => x.Item1 == workflowId && x.Item2 == version); + var definition = _registry.FirstOrDefault(x => x.Item1 == workflowId && x.Item2 == version); if (definition != null) { - _registry.Remove(definition); + _registry.TryTake(out definition); } } @@ -81,7 +82,7 @@ public void RegisterWorkflow(IWorkflow workflow) public bool IsRegistered(string workflowId, int version) { - var definition = _registry.Find(x => x.Item1 == workflowId && x.Item2 == version); + var definition = _registry.FirstOrDefault(x => x.Item1 == workflowId && x.Item2 == version); return (definition != null); } From 4b3422e14315acb303236b22c32cee211db1cc8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=91=E9=9B=B60=E4=B8=83?= <007@wangshuai.app> Date: Tue, 20 Oct 2020 11:03:13 +0800 Subject: [PATCH 038/342] add support for WorkflowStep Before, the `StepType` field must be subclass of StepBody Now,It support for `WorkflowStep` Old: public class HelloWorld : StepBody new:(Add) public class EndStep : WorkflowStep --- .../Services/DefinitionLoader.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index 810d6338b..27d84492b 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -68,8 +68,22 @@ private WorkflowStepCollection ConvertSteps(ICollection source, Ty var nextStep = stack.Pop(); var stepType = FindType(nextStep.StepType); - var containerType = typeof(WorkflowStep<>).MakeGenericType(stepType); - var targetStep = (containerType.GetConstructor(new Type[] { }).Invoke(null) as WorkflowStep); + + WorkflowStep targetStep; + + Type containerType; + if (stepType.IsSubclassOf(typeof(StepBody))) + { + containerType = typeof(WorkflowStep<>).MakeGenericType(stepType); + + targetStep = (containerType.GetConstructor(new Type[] { }).Invoke(null) as WorkflowStep); + } + else + { + targetStep = stepType.GetConstructor(new Type[] { }).Invoke(null) as WorkflowStep; + if (targetStep != null) + stepType = targetStep.BodyType; + } if (nextStep.Saga) { From 665e945d94da566acac6e6b9fffccd1da6295d4f Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 21 Oct 2020 17:37:15 -0700 Subject: [PATCH 039/342] pass current context to default branch --- src/WorkflowCore/Primitives/If.cs | 2 +- src/WorkflowCore/Primitives/OutcomeSwitch.cs | 2 +- src/WorkflowCore/Primitives/Schedule.cs | 2 +- src/WorkflowCore/Primitives/Sequence.cs | 2 +- src/WorkflowCore/Primitives/When.cs | 2 +- src/WorkflowCore/Primitives/While.cs | 2 +- src/WorkflowCore/WorkflowCore.csproj | 8 ++++---- src/extensions/WorkflowCore.Users/Primitives/UserTask.cs | 2 +- .../WorkflowCore.Users/WorkflowCore.Users.csproj | 6 +++--- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/WorkflowCore/Primitives/If.cs b/src/WorkflowCore/Primitives/If.cs index 2aaaad963..1f7085788 100644 --- a/src/WorkflowCore/Primitives/If.cs +++ b/src/WorkflowCore/Primitives/If.cs @@ -15,7 +15,7 @@ public override ExecutionResult Run(IStepExecutionContext context) { if (Condition) { - return ExecutionResult.Branch(new List() { null }, new ControlPersistenceData() { ChildrenActive = true }); + return ExecutionResult.Branch(new List() { context.Item }, new ControlPersistenceData() { ChildrenActive = true }); } return ExecutionResult.Next(); diff --git a/src/WorkflowCore/Primitives/OutcomeSwitch.cs b/src/WorkflowCore/Primitives/OutcomeSwitch.cs index 74c2cf1de..d2dcc1e79 100644 --- a/src/WorkflowCore/Primitives/OutcomeSwitch.cs +++ b/src/WorkflowCore/Primitives/OutcomeSwitch.cs @@ -12,7 +12,7 @@ public override ExecutionResult Run(IStepExecutionContext context) { if (context.PersistenceData == null) { - var result = ExecutionResult.Branch(new List() { null }, new ControlPersistenceData() { ChildrenActive = true }); + var result = ExecutionResult.Branch(new List() { context.Item }, new ControlPersistenceData() { ChildrenActive = true }); result.OutcomeValue = GetPreviousOutcome(context); return result; } diff --git a/src/WorkflowCore/Primitives/Schedule.cs b/src/WorkflowCore/Primitives/Schedule.cs index 9c74f2a97..e279cb232 100644 --- a/src/WorkflowCore/Primitives/Schedule.cs +++ b/src/WorkflowCore/Primitives/Schedule.cs @@ -20,7 +20,7 @@ public override ExecutionResult Run(IStepExecutionContext context) { if (!((SchedulePersistenceData)context.PersistenceData).Elapsed) { - return ExecutionResult.Branch(new List() { null }, new SchedulePersistenceData() { Elapsed = true }); + return ExecutionResult.Branch(new List() { context.Item }, new SchedulePersistenceData() { Elapsed = true }); } if (context.Workflow.IsBranchComplete(context.ExecutionPointer.Id)) diff --git a/src/WorkflowCore/Primitives/Sequence.cs b/src/WorkflowCore/Primitives/Sequence.cs index 20140af47..d31206a79 100644 --- a/src/WorkflowCore/Primitives/Sequence.cs +++ b/src/WorkflowCore/Primitives/Sequence.cs @@ -11,7 +11,7 @@ public override ExecutionResult Run(IStepExecutionContext context) { if (context.PersistenceData == null) { - return ExecutionResult.Branch(new List() { null }, new ControlPersistenceData() { ChildrenActive = true }); + return ExecutionResult.Branch(new List() { context.Item }, new ControlPersistenceData() { ChildrenActive = true }); } if ((context.PersistenceData is ControlPersistenceData) && ((context.PersistenceData as ControlPersistenceData).ChildrenActive)) diff --git a/src/WorkflowCore/Primitives/When.cs b/src/WorkflowCore/Primitives/When.cs index ca9434f66..f5f292ad1 100644 --- a/src/WorkflowCore/Primitives/When.cs +++ b/src/WorkflowCore/Primitives/When.cs @@ -25,7 +25,7 @@ public override ExecutionResult Run(IStepExecutionContext context) if (context.PersistenceData == null) { - return ExecutionResult.Branch(new List() { null }, new ControlPersistenceData() { ChildrenActive = true }); + return ExecutionResult.Branch(new List() { context.Item }, new ControlPersistenceData() { ChildrenActive = true }); } if ((context.PersistenceData is ControlPersistenceData) && ((context.PersistenceData as ControlPersistenceData).ChildrenActive)) diff --git a/src/WorkflowCore/Primitives/While.cs b/src/WorkflowCore/Primitives/While.cs index 154d7cf87..ba5abc2e6 100644 --- a/src/WorkflowCore/Primitives/While.cs +++ b/src/WorkflowCore/Primitives/While.cs @@ -15,7 +15,7 @@ public override ExecutionResult Run(IStepExecutionContext context) { if (Condition) { - return ExecutionResult.Branch(new List() { null }, new ControlPersistenceData() { ChildrenActive = true }); + return ExecutionResult.Branch(new List() { context.Item }, new ControlPersistenceData() { ChildrenActive = true }); } return ExecutionResult.Next(); diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index d3a447a9f..c4ff1258a 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.2.5 - 3.2.5.0 - 3.2.5.0 + 3.2.6 + 3.2.6.0 + 3.2.6.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.2.5 + 3.2.6 diff --git a/src/extensions/WorkflowCore.Users/Primitives/UserTask.cs b/src/extensions/WorkflowCore.Users/Primitives/UserTask.cs index 5f67ca443..a1edd9b72 100644 --- a/src/extensions/WorkflowCore.Users/Primitives/UserTask.cs +++ b/src/extensions/WorkflowCore.Users/Primitives/UserTask.cs @@ -50,7 +50,7 @@ public override ExecutionResult Run(IStepExecutionContext context) if (context.PersistenceData == null) { - var result = ExecutionResult.Branch(new List() { null }, new ControlPersistenceData() { ChildrenActive = true }); + var result = ExecutionResult.Branch(new List() { context.Item }, new ControlPersistenceData() { ChildrenActive = true }); result.OutcomeValue = action.OutcomeValue; return result; } diff --git a/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj b/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj index 742f848f5..5a8c0beab 100644 --- a/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj +++ b/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj @@ -15,9 +15,9 @@ false false Provides extensions for Workflow Core to enable human workflows. - 2.1.0 - 2.1.0.0 - 2.1.0.0 + 2.1.1 + 2.1.1.0 + 2.1.1.0 From 2aaf7bddef4eac9c0f3f6ad205b9090c3ec40d21 Mon Sep 17 00:00:00 2001 From: DanilF Date: Mon, 19 Oct 2020 16:18:20 -0400 Subject: [PATCH 040/342] Add middleware runner, step executor, and ability to run middleware around workflow steps and before/after workflow Add sample with a sample middleware for retrying and log correlation as well as workflow pre/post samples Add async overloads for StartWorkflow and WaitForWorkflowToComplete in integration tests Add error handling of post workflow middleware Add docs for workflow middleware --- WorkflowCore.sln | 7 + docs/samples.md | 4 +- docs/workflow-middleware.md | 279 ++++++++++++++++++ mkdocs.yml | 1 + .../Models/v1/DefinitionSourceV1.cs | 1 - .../Services/DefinitionLoader.cs | 4 +- src/WorkflowCore/Interface/IStepExecutor.cs | 22 ++ .../Interface/IWorkflowBuilder.cs | 7 +- .../Interface/IWorkflowMiddleware.cs | 41 +++ .../IWorkflowMiddlewareErrorHandler.cs | 18 ++ .../Interface/IWorkflowMiddlewareRunner.cs | 33 +++ .../Interface/IWorkflowStepMiddleware.cs | 28 ++ src/WorkflowCore/Models/WorkflowDefinition.cs | 12 +- src/WorkflowCore/Models/WorkflowDelegate.cs | 9 + .../Models/WorkflowStepDelegate.cs | 9 + .../ServiceCollectionExtensions.cs | 39 ++- .../DefaultWorkflowMiddlewareErrorHandler.cs | 32 ++ .../FluentBuilders/WorkflowBuilder.cs | 2 +- src/WorkflowCore/Services/StepExecutor.cs | 52 ++++ .../Services/WorkflowController.cs | 10 +- src/WorkflowCore/Services/WorkflowExecutor.cs | 34 ++- .../Services/WorkflowMiddlewareRunner.cs | 96 ++++++ .../FlakyConnectionParams.cs | 9 + .../FlakyConnectionWorkflow.cs | 25 ++ .../IDescriptiveWorkflowParams.cs | 7 + .../AddDescriptionWorkflowMiddleware.cs | 20 ++ .../LogCorrelationStepMiddleware.cs | 38 +++ .../Middleware/PollyRetryMiddleware.cs | 63 ++++ .../PrintWorkflowSummaryMiddleware.cs | 41 +++ src/samples/WorkflowCore.Sample19/Program.cs | 66 +++++ .../Steps/FlakyConnection.cs | 27 ++ .../WorkflowCore.Sample19/Steps/LogMessage.cs | 29 ++ .../WorkflowCore.Sample19.csproj | 20 ++ .../Scenarios/MiddlewareScenario.cs | 167 +++++++++++ .../Scenarios/StoredJsonScenario.cs | 3 +- .../Scenarios/StoredYamlScenario.cs | 3 +- .../DistributedLockProviderTests.cs | 11 +- .../stored-definition.json | 2 +- test/WorkflowCore.Testing/JsonWorkflowTest.cs | 4 +- test/WorkflowCore.Testing/WorkflowTest.cs | 24 +- test/WorkflowCore.Testing/YamlWorkflowTest.cs | 3 +- .../Services/StepExecutorTests.cs | 148 ++++++++++ .../Services/WorkflowExecutorFixture.cs | 45 ++- .../Services/WorkflowMiddlewareRunnerTests.cs | 276 +++++++++++++++++ 44 files changed, 1713 insertions(+), 58 deletions(-) create mode 100644 docs/workflow-middleware.md create mode 100644 src/WorkflowCore/Interface/IStepExecutor.cs create mode 100644 src/WorkflowCore/Interface/IWorkflowMiddleware.cs create mode 100644 src/WorkflowCore/Interface/IWorkflowMiddlewareErrorHandler.cs create mode 100644 src/WorkflowCore/Interface/IWorkflowMiddlewareRunner.cs create mode 100644 src/WorkflowCore/Interface/IWorkflowStepMiddleware.cs create mode 100644 src/WorkflowCore/Models/WorkflowDelegate.cs create mode 100644 src/WorkflowCore/Models/WorkflowStepDelegate.cs create mode 100644 src/WorkflowCore/Services/DefaultWorkflowMiddlewareErrorHandler.cs create mode 100644 src/WorkflowCore/Services/StepExecutor.cs create mode 100644 src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs create mode 100644 src/samples/WorkflowCore.Sample19/FlakyConnectionParams.cs create mode 100644 src/samples/WorkflowCore.Sample19/FlakyConnectionWorkflow.cs create mode 100644 src/samples/WorkflowCore.Sample19/IDescriptiveWorkflowParams.cs create mode 100644 src/samples/WorkflowCore.Sample19/Middleware/AddDescriptionWorkflowMiddleware.cs create mode 100644 src/samples/WorkflowCore.Sample19/Middleware/LogCorrelationStepMiddleware.cs create mode 100644 src/samples/WorkflowCore.Sample19/Middleware/PollyRetryMiddleware.cs create mode 100644 src/samples/WorkflowCore.Sample19/Middleware/PrintWorkflowSummaryMiddleware.cs create mode 100644 src/samples/WorkflowCore.Sample19/Program.cs create mode 100644 src/samples/WorkflowCore.Sample19/Steps/FlakyConnection.cs create mode 100644 src/samples/WorkflowCore.Sample19/Steps/LogMessage.cs create mode 100644 src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj create mode 100644 test/WorkflowCore.IntegrationTests/Scenarios/MiddlewareScenario.cs create mode 100644 test/WorkflowCore.UnitTests/Services/StepExecutorTests.cs create mode 100644 test/WorkflowCore.UnitTests/Services/WorkflowMiddlewareRunnerTests.cs diff --git a/WorkflowCore.sln b/WorkflowCore.sln index 9231faa76..09cda3de8 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -147,6 +147,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScratchPad", "test\ScratchP EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Tests.QueueProviders.RabbitMQ", "test\WorkflowCore.Tests.QueueProviders.RabbitMQ\WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj", "{54DE20BA-EBA7-4BF0-9BD9-F03766849716}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Sample19", "src\samples\WorkflowCore.Sample19\WorkflowCore.Sample19.csproj", "{1223ED47-3E5E-4960-B70D-DFAF550F6666}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -361,6 +363,10 @@ Global {54DE20BA-EBA7-4BF0-9BD9-F03766849716}.Debug|Any CPU.Build.0 = Debug|Any CPU {54DE20BA-EBA7-4BF0-9BD9-F03766849716}.Release|Any CPU.ActiveCfg = Release|Any CPU {54DE20BA-EBA7-4BF0-9BD9-F03766849716}.Release|Any CPU.Build.0 = Release|Any CPU + {1223ED47-3E5E-4960-B70D-DFAF550F6666}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1223ED47-3E5E-4960-B70D-DFAF550F6666}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1223ED47-3E5E-4960-B70D-DFAF550F6666}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1223ED47-3E5E-4960-B70D-DFAF550F6666}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -421,6 +427,7 @@ Global {E32CF21A-29CC-46D1-8044-FCC327F2B281} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} {51BB7DCD-01DD-453D-A1E7-17E5E3DBB14C} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} {54DE20BA-EBA7-4BF0-9BD9-F03766849716} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} + {1223ED47-3E5E-4960-B70D-DFAF550F6666} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC0FA8D3-6449-4FDA-BB46-ECF58FAD23B4} diff --git a/docs/samples.md b/docs/samples.md index a1b862799..f69290c57 100644 --- a/docs/samples.md +++ b/docs/samples.md @@ -32,4 +32,6 @@ [Exposing a REST API](https://github.com/danielgerlag/workflow-core/tree/master/src/samples/WebApiSample) -[Human(User) Workflow](https://github.com/danielgerlag/workflow-core/tree/master/src/samples/WorkflowCore.Sample08) \ No newline at end of file +[Human(User) Workflow](https://github.com/danielgerlag/workflow-core/tree/master/src/samples/WorkflowCore.Sample08) + +[Workflow Middleware](https://github.com/danielgerlag/workflow-core/tree/master/src/samples/WorkflowCore.Sample19) diff --git a/docs/workflow-middleware.md b/docs/workflow-middleware.md new file mode 100644 index 000000000..488d0c7ad --- /dev/null +++ b/docs/workflow-middleware.md @@ -0,0 +1,279 @@ +# Workflow Middleware + +Workflows can be extended with Middleware that run before/after workflows start/complete as well as around workflow steps to provide flexibility in implementing cross-cutting concerns such as [log correlation](https://www.frakkingsweet.com/net-core-log-correlation-easy-access-to-headers/), [retries](https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/implement-http-call-retries-exponential-backoff-polly), and other use-cases. + +This is done by implementing and registering `IWorkflowMiddleware` for workflows or `IWorkflowStepMiddleware` for steps. + +## Step Middleware + +Step middleware lets you run additional code around the execution of a given step and alter its behavior. Implementing a step middleware should look familiar to anyone familiar with [ASP.NET Core's middleware pipeline](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.1) or [`HttpClient`'s `DelegatingHandler` middleware](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1#outgoing-request-middleware). + +### Usage + +First, create your own middleware class that implements `IWorkflowStepMiddleware`. Here's an example of a middleware that adds workflow ID and step ID to the log correlation context of every workflow step in your app. + +**Important:** You must make sure to call `next()` as part of your middleware. If you do not do this, your step will never run. + +```cs +public class LogCorrelationStepMiddleware : IWorkflowStepMiddleware +{ + private readonly ILogger _log; + + public LogCorrelationStepMiddleware( + ILogger log) + { + _log = log; + } + + public async Task HandleAsync( + IStepExecutionContext context, + IStepBody body, + WorkflowStepDelegate next) + { + var workflowId = context.Workflow.Id; + var stepId = context.Step.Id; + + // Uses log scope to add a few attributes to the scope + using (_log.BeginScope("{@WorkflowId}", workflowId)) + using (_log.BeginScope("{@StepId}", stepId)) + { + // Calling next ensures step gets executed + return await next(); + } + } +} +``` + +Here's another example of a middleware that uses the [Polly](https://github.com/App-vNext/Polly) dotnet resiliency library to implement retries on workflow steps based off a custom retry policy. + +```cs +public class PollyRetryStepMiddleware : IWorkflowStepMiddleware +{ + private const string StepContextKey = "WorkflowStepContext"; + private const int MaxRetries = 3; + private readonly ILogger _log; + + public PollyRetryMiddleware(ILogger log) + { + _log = log; + } + + // Consult Polly's docs for more information on how to build + // retry policies: + // https://github.com/App-vNext/Polly + public IAsyncPolicy GetRetryPolicy() => + Policy + .Handle() + .RetryAsync( + MaxRetries, + (result, retryCount, context) => + UpdateRetryCount( + result.Exception, + retryCount, + context[StepContextKey] as IStepExecutionContext) + ); + + public async Task HandleAsync( + IStepExecutionContext context, + IStepBody body, + WorkflowStepDelegate next + ) + { + return await GetRetryPolicy().ExecuteAsync( + ctx => next(), + // The step execution context gets passed down so that + // the step is accessible within the retry policy + new Dictionary + { + { StepContextKey, context } + }); + } + + private Task UpdateRetryCount( + Exception exception, + int retryCount, + IStepExecutionContext stepContext) + { + var stepInstance = stepContext.ExecutionPointer; + stepInstance.RetryCount = retryCount; + return Task.CompletedTask; + } +} +``` + +## Pre/Post Workflow Middleware + +Workflow middleware run either before a workflow starts or after a workflow completes and can be used to hook into the workflow lifecycle or alter the workflow itself before it is started. + +### Pre Workflow Middleware + +These middleware get run before the workflow is started and can potentially alter properties on the `WorkflowInstance`. + +The following example illustrates setting the `Description` property on the `WorkflowInstance` using a middleware that interprets the data on the passed workflow. This is useful in cases where you want the description of the workflow to be derived from the data passed to the workflow. + +Note that you use `WorkflowMiddlewarePhase.PreWorkflow` to specify that it runs before the workflow starts. + +**Important:** You should call `next` as part of the workflow middleware to ensure that the next workflow in the chain runs. + +```cs +// AddDescriptionWorkflowMiddleware.cs +public class AddDescriptionWorkflowMiddleware : IWorkflowMiddleware +{ + public WorkflowMiddlewarePhase Phase => + WorkflowMiddlewarePhase.PreWorkflow; + + public Task HandleAsync( + WorkflowInstance workflow, + WorkflowDelegate next + ) + { + if (workflow.Data is IDescriptiveWorkflowParams descriptiveParams) + { + workflow.Description = descriptiveParams.Description; + } + + return next(); + } +} + +// IDescriptiveWorkflowParams.cs +public interface IDescriptiveWorkflowParams +{ + string Description { get; } +} + +// MyWorkflowParams.cs +public MyWorkflowParams : IDescriptiveWorkflowParams +{ + public string Description => $"Run task '{TaskName}'"; + + public string TaskName { get; set; } +} +``` + +### Exception Handling in Pre Workflow Middleware + +Pre workflow middleware exception handling gets treated differently from post workflow middleware. Since the middleware runs before the workflow starts, any exceptions thrown within a pre workflow middleware will bubble up to the `StartWorkflow` method and it is up to the caller of `StartWorkflow` to handle the exception and act accordingly. + +```cs +public async Task MyMethodThatStartsAWorkflow() +{ + try + { + await host.StartWorkflow("HelloWorld", 1, null); + } + catch(Exception ex) + { + // Handle the exception appropriately + } +} +``` + +### Post Workflow Middleware + +These middleware get run after the workflow has completed and can be used to perform additional actions for all workflows in your app. + +The following example illustrates how you can use a post workflow middleware to print a summary of the workflow to console. + +Note that you use `WorkflowMiddlewarePhase.PostWorkflow` to specify that it runs after the workflow completes. + +**Important:** You should call `next` as part of the workflow middleware to ensure that the next workflow in the chain runs. + +```cs +public class PrintWorkflowSummaryMiddleware : IWorkflowMiddleware +{ + private readonly ILogger _log; + + public PrintWorkflowSummaryMiddleware( + ILogger log + ) + { + _log = log; + } + + public WorkflowMiddlewarePhase Phase => + WorkflowMiddlewarePhase.PostWorkflow; + + public Task HandleAsync( + WorkflowInstance workflow, + WorkflowDelegate next + ) + { + if (!workflow.CompleteTime.HasValue) + { + return next(); + } + + var duration = workflow.CompleteTime.Value - workflow.CreateTime; + _log.LogInformation($@"Workflow {workflow.Description} completed in {duration:g}"); + + foreach (var step in workflow.ExecutionPointers) + { + var stepName = step.StepName; + var stepDuration = (step.EndTime - step.StartTime) ?? TimeSpan.Zero; + _log.LogInformation($" - Step {stepName} completed in {stepDuration:g}"); + } + + return next(); + } +} +``` + +### Exception Handling in Post Workflow Middleware + +Post workflow middleware exception handling gets treated differently from pre workflow middleware. At the time that the workflow completes, your workflow has ran already so an uncaught exception would be difficult to act on. + +By default, if a workflow middleware throws an exception, it will be logged and the workflow will complete as normal. This behavior can be changed, however. + +To override the default post workflow error handling for all workflows in your app, just register a new `IWorkflowMiddlewareErrorHandler` in the dependency injection framework with your custom behavior as follows. + +```cs +// CustomMiddlewareErrorHandler.cs +public class CustomHandler : IWorkflowMiddlewareErrorHandler +{ + public Task HandleAsync(Exception ex) + { + // Handle your error asynchronously + } +} + +// Startup.cs +public void ConfigureServices(IServiceCollection services) +{ + // Other workflow configuration + services.AddWorkflow(); + + // Should go after .AddWorkflow() + services.AddTransient(); +} +``` + +## Registering Middleware + +In order for middleware to take effect, they must be registered with the built-in dependency injection framework using the convenience helpers. + +**Note:** Middleware will be run in the order that they are registered with middleware that are registered earlier running earlier in the chain and finishing later in the chain. For pre/post workflow middleware, all pre middleware will be run before a workflow starts and all post middleware will be run after a workflow completes. + +```cs +public class Startup +{ + public void ConfigureServices(IServiceCollection services) + { + ... + + // Add workflow middleware + services.AddWorkflowMiddleware(); + services.AddWorkflowMiddleware(); + + // Add step middleware + services.AddWorkflowStepMiddleware(); + services.AddWorkflowStepMiddleware(); + + ... + } +} +``` + +## More Information + +See the [Workflow Middleware](https://github.com/danielgerlag/workflow-core/tree/master/src/samples/WorkflowCore.Sample19) sample for full examples of workflow middleware in action. diff --git a/mkdocs.yml b/mkdocs.yml index fcbf9e4a8..57ed12c94 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -9,6 +9,7 @@ nav: - Saga transactions: sagas.md - JSON / YAML Definitions: json-yaml.md - Persistence: persistence.md + - Middleware: workflow-middleware.md - Multi-node clusters: multi-node-clusters.md - ASP.NET Core: using-with-aspnet-core.md - Elasticsearch plugin: elastic-search.md diff --git a/src/WorkflowCore.DSL/Models/v1/DefinitionSourceV1.cs b/src/WorkflowCore.DSL/Models/v1/DefinitionSourceV1.cs index 1de64c35e..46f0521ca 100644 --- a/src/WorkflowCore.DSL/Models/v1/DefinitionSourceV1.cs +++ b/src/WorkflowCore.DSL/Models/v1/DefinitionSourceV1.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.DefinitionStorage.v1 { diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index 810d6338b..0f5a89558 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -93,7 +93,7 @@ private WorkflowStepCollection ConvertSteps(ICollection source, Ty AttachInputs(nextStep, dataType, stepType, targetStep); AttachOutputs(nextStep, dataType, stepType, targetStep); - + if (nextStep.Do != null) { foreach (var branch in nextStep.Do) @@ -242,7 +242,7 @@ private void AttachOutcomes(StepSourceV1 source, Type dataType, WorkflowStep ste var outcomeParameter = Expression.Parameter(typeof(object), "outcome"); foreach (var nextStep in source.SelectNextStep) - { + { var sourceDelegate = DynamicExpressionParser.ParseLambda(new[] { dataParameter, outcomeParameter }, typeof(object), nextStep.Value).Compile(); Expression> sourceExpr = (data, outcome) => System.Convert.ToBoolean(sourceDelegate.DynamicInvoke(data, outcome)); step.Outcomes.Add(new ExpressionOutcome(sourceExpr) diff --git a/src/WorkflowCore/Interface/IStepExecutor.cs b/src/WorkflowCore/Interface/IStepExecutor.cs new file mode 100644 index 000000000..aed3d3026 --- /dev/null +++ b/src/WorkflowCore/Interface/IStepExecutor.cs @@ -0,0 +1,22 @@ +using System.Threading.Tasks; +using WorkflowCore.Models; + +namespace WorkflowCore.Interface +{ + /// + /// Executes a workflow step. + /// + public interface IStepExecutor + { + /// + /// Runs the passed in the given . + /// + /// The in which to execute the step. + /// The body. + /// A to wait for the result of running the step + Task ExecuteStep( + IStepExecutionContext context, + IStepBody body + ); + } +} diff --git a/src/WorkflowCore/Interface/IWorkflowBuilder.cs b/src/WorkflowCore/Interface/IWorkflowBuilder.cs index ec7b7bad2..b7b371882 100644 --- a/src/WorkflowCore/Interface/IWorkflowBuilder.cs +++ b/src/WorkflowCore/Interface/IWorkflowBuilder.cs @@ -9,7 +9,7 @@ public interface IWorkflowBuilder { List Steps { get; } - int LastStep { get; } + int LastStep { get; } IWorkflowBuilder UseData(); @@ -21,7 +21,7 @@ public interface IWorkflowBuilder } public interface IWorkflowBuilder : IWorkflowBuilder, IWorkflowModifier - { + { IStepBuilder StartWith(Action> stepSetup = null) where TStep : IStepBody; IStepBuilder StartWith(Func body); @@ -33,6 +33,5 @@ public interface IWorkflowBuilder : IWorkflowBuilder, IWorkflowModifier UseDefaultErrorBehavior(WorkflowErrorHandling behavior, TimeSpan? retryInterval = null); IWorkflowBuilder CreateBranch(); - } -} \ No newline at end of file +} diff --git a/src/WorkflowCore/Interface/IWorkflowMiddleware.cs b/src/WorkflowCore/Interface/IWorkflowMiddleware.cs new file mode 100644 index 000000000..71781b30d --- /dev/null +++ b/src/WorkflowCore/Interface/IWorkflowMiddleware.cs @@ -0,0 +1,41 @@ +using System.Threading.Tasks; +using WorkflowCore.Models; + +namespace WorkflowCore.Interface +{ + /// + /// Determines at which point to run the middleware. + /// + public enum WorkflowMiddlewarePhase + { + /// + /// The middleware should run before a workflow starts. + /// + PreWorkflow, + + /// + /// The middleware should run after a workflow completes. + /// + PostWorkflow + } + + /// + /// Middleware that can run before a workflow starts or after a workflow completes. + /// + public interface IWorkflowMiddleware + { + /// + /// The phase in the workflow execution to run this middleware in + /// + WorkflowMiddlewarePhase Phase { get; } + + /// + /// Runs the middleware on the given . + /// + /// The . + /// The next middleware in the chain. + /// A that completes asynchronously once the + /// middleware chain finishes running. + Task HandleAsync(WorkflowInstance workflow, WorkflowDelegate next); + } +} diff --git a/src/WorkflowCore/Interface/IWorkflowMiddlewareErrorHandler.cs b/src/WorkflowCore/Interface/IWorkflowMiddlewareErrorHandler.cs new file mode 100644 index 000000000..5522bae39 --- /dev/null +++ b/src/WorkflowCore/Interface/IWorkflowMiddlewareErrorHandler.cs @@ -0,0 +1,18 @@ +using System; +using System.Threading.Tasks; + +namespace WorkflowCore.Interface +{ + /// + /// Handles exceptions within workflow middleware. + /// + public interface IWorkflowMiddlewareErrorHandler + { + /// + /// Asynchronously handle the given exception. + /// + /// The exception to handle + /// A task that completes when handling is done. + Task HandleAsync(Exception ex); + } +} diff --git a/src/WorkflowCore/Interface/IWorkflowMiddlewareRunner.cs b/src/WorkflowCore/Interface/IWorkflowMiddlewareRunner.cs new file mode 100644 index 000000000..96aab8b74 --- /dev/null +++ b/src/WorkflowCore/Interface/IWorkflowMiddlewareRunner.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using WorkflowCore.Models; + +namespace WorkflowCore.Interface +{ + /// + /// Runs workflow pre/post middleware. + /// + public interface IWorkflowMiddlewareRunner + { + /// + /// Runs workflow-level middleware that is set to run at the + /// phase. Middleware will be run in the + /// order in which they were registered with DI with middleware declared earlier starting earlier and + /// completing later. + /// + /// The to run for. + /// The definition. + /// A task that will complete when all middleware has run. + Task RunPreMiddleware(WorkflowInstance workflow, WorkflowDefinition def); + + /// + /// Runs workflow-level middleware that is set to run at the + /// phase. Middleware will be run in the + /// order in which they were registered with DI with middleware declared earlier starting earlier and + /// completing later. + /// + /// The to run for. + /// The definition. + /// A task that will complete when all middleware has run. + Task RunPostMiddleware(WorkflowInstance workflow, WorkflowDefinition def); + } +} diff --git a/src/WorkflowCore/Interface/IWorkflowStepMiddleware.cs b/src/WorkflowCore/Interface/IWorkflowStepMiddleware.cs new file mode 100644 index 000000000..91f888589 --- /dev/null +++ b/src/WorkflowCore/Interface/IWorkflowStepMiddleware.cs @@ -0,0 +1,28 @@ +using System.Threading.Tasks; +using WorkflowCore.Models; + +namespace WorkflowCore.Interface +{ + /// + /// Middleware that runs around a workflow step and can enhance or alter + /// the steps behavior. + /// + public interface IWorkflowStepMiddleware + { + /// + /// Handle the workflow step and return an + /// asynchronously. It is important to invoke at some point + /// in the middleware. Not doing so will prevent the workflow step from ever + /// getting executed. + /// + /// The step's context. + /// An instance of the step body that is going to be run. + /// The next middleware in the chain. + /// A of the workflow result. + Task HandleAsync( + IStepExecutionContext context, + IStepBody body, + WorkflowStepDelegate next + ); + } +} diff --git a/src/WorkflowCore/Models/WorkflowDefinition.cs b/src/WorkflowCore/Models/WorkflowDefinition.cs index f39a563ed..207457e19 100644 --- a/src/WorkflowCore/Models/WorkflowDefinition.cs +++ b/src/WorkflowCore/Models/WorkflowDefinition.cs @@ -18,14 +18,16 @@ public class WorkflowDefinition public WorkflowErrorHandling DefaultErrorBehavior { get; set; } - public TimeSpan? DefaultErrorRetryInterval { get; set; } + public Type OnPostMiddlewareError { get; set; } + + public TimeSpan? DefaultErrorRetryInterval { get; set; } } - public enum WorkflowErrorHandling - { - Retry = 0, - Suspend = 1, + public enum WorkflowErrorHandling + { + Retry = 0, + Suspend = 1, Terminate = 2, Compensate = 3 } diff --git a/src/WorkflowCore/Models/WorkflowDelegate.cs b/src/WorkflowCore/Models/WorkflowDelegate.cs new file mode 100644 index 000000000..2d8876163 --- /dev/null +++ b/src/WorkflowCore/Models/WorkflowDelegate.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace WorkflowCore.Models +{ + /// + /// Represents a function that executes before or after a workflow starts or completes. + /// + public delegate Task WorkflowDelegate(); +} diff --git a/src/WorkflowCore/Models/WorkflowStepDelegate.cs b/src/WorkflowCore/Models/WorkflowStepDelegate.cs new file mode 100644 index 000000000..21befb575 --- /dev/null +++ b/src/WorkflowCore/Models/WorkflowStepDelegate.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace WorkflowCore.Models +{ + /// + /// Represents a function that executes a workflow step and returns a result. + /// + public delegate Task WorkflowStepDelegate(); +} diff --git a/src/WorkflowCore/ServiceCollectionExtensions.cs b/src/WorkflowCore/ServiceCollectionExtensions.cs index 6fe511845..8598abe03 100644 --- a/src/WorkflowCore/ServiceCollectionExtensions.cs +++ b/src/WorkflowCore/ServiceCollectionExtensions.cs @@ -35,7 +35,7 @@ public static IServiceCollection AddWorkflow(this IServiceCollection services, A services.AddSingleton(); services.AddSingleton(options); - services.AddSingleton(); + services.AddSingleton(); services.AddTransient(); services.AddTransient(); @@ -51,6 +51,9 @@ public static IServiceCollection AddWorkflow(this IServiceCollection services, A services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddTransient(); services.AddTransient(); @@ -69,6 +72,40 @@ public static IServiceCollection AddWorkflow(this IServiceCollection services, A return services; } + + /// + /// Adds a middleware that will run around the execution of a workflow step. + /// + /// The services collection. + /// Optionally configure using your own factory. + /// The type of middleware. + /// It must implement . + /// The services collection for chaining. + public static IServiceCollection AddWorkflowStepMiddleware( + this IServiceCollection services, + Func factory = null) + where TMiddleware : class, IWorkflowStepMiddleware => + factory == null + ? services.AddTransient() + : services.AddTransient(factory); + + /// + /// Adds a middleware that will run either before a workflow is kicked off or after + /// a workflow completes. Specify the phase of the workflow execution process that + /// you want to execute this middleware using . + /// + /// The services collection. + /// Optionally configure using your own factory. + /// The type of middleware. + /// It must implement . + /// The services collection for chaining. + public static IServiceCollection AddWorkflowMiddleware( + this IServiceCollection services, + Func factory = null) + where TMiddleware : class, IWorkflowMiddleware => + factory == null + ? services.AddTransient() + : services.AddTransient(factory); } } diff --git a/src/WorkflowCore/Services/DefaultWorkflowMiddlewareErrorHandler.cs b/src/WorkflowCore/Services/DefaultWorkflowMiddlewareErrorHandler.cs new file mode 100644 index 000000000..99c4652ff --- /dev/null +++ b/src/WorkflowCore/Services/DefaultWorkflowMiddlewareErrorHandler.cs @@ -0,0 +1,32 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using WorkflowCore.Interface; + +namespace WorkflowCore.Services +{ + /// + /// Default implementation of . Just logs the + /// thrown exception and moves on. + /// + public class DefaultWorkflowMiddlewareErrorHandler : IWorkflowMiddlewareErrorHandler + { + private readonly ILogger _log; + + public DefaultWorkflowMiddlewareErrorHandler(ILogger log) + { + _log = log; + } + + /// + /// Asynchronously handle the given exception. + /// + /// The exception to handle + /// A task that completes when handling is done. + public Task HandleAsync(Exception ex) + { + _log.LogError(ex, "An error occurred running workflow middleware: {Message}", ex.Message); + return Task.CompletedTask; + } + } +} diff --git a/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs b/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs index f5acd7694..98788fa0c 100644 --- a/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs +++ b/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs @@ -225,7 +225,7 @@ public IContainerStepBuilder ForEach(Expression ForEach(Expression> collection, Expression> runParallel) { return Start().ForEach(collection, runParallel); diff --git a/src/WorkflowCore/Services/StepExecutor.cs b/src/WorkflowCore/Services/StepExecutor.cs new file mode 100644 index 000000000..4e45574e5 --- /dev/null +++ b/src/WorkflowCore/Services/StepExecutor.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Services +{ + /// + /// Executes the workflow step and applies any to the step. + /// + public class StepExecutor : IStepExecutor + { + private readonly IEnumerable _stepMiddleware; + + public StepExecutor( + IEnumerable stepMiddleware + ) + { + _stepMiddleware = stepMiddleware; + } + + /// + /// Runs the passed in the given while applying + /// any registered in the system. Middleware will be run in the + /// order in which they were registered with DI with middleware declared earlier starting earlier and + /// completing later. + /// + /// The in which to execute the step. + /// The body. + /// A to wait for the result of running the step + public async Task ExecuteStep( + IStepExecutionContext context, + IStepBody body + ) + { + // Build the middleware chain by reducing over all the middleware in reverse starting with step body + // and building step delegates that call out to the next delegate in the chain + Task Step() => body.RunAsync(context); + var middlewareChain = _stepMiddleware + .Reverse() + .Aggregate( + (WorkflowStepDelegate) Step, + (previous, middleware) => () => middleware.HandleAsync(context, body, previous) + ); + + // Run the middleware chain + return await middlewareChain(); + } + } +} diff --git a/src/WorkflowCore/Services/WorkflowController.cs b/src/WorkflowCore/Services/WorkflowController.cs index 203da3139..20b7621d9 100755 --- a/src/WorkflowCore/Services/WorkflowController.cs +++ b/src/WorkflowCore/Services/WorkflowController.cs @@ -21,9 +21,10 @@ public class WorkflowController : IWorkflowController private readonly IExecutionPointerFactory _pointerFactory; private readonly ILifeCycleEventHub _eventHub; private readonly IServiceProvider _serviceProvider; + private readonly IWorkflowMiddlewareRunner _middlewareRunner; private readonly ILogger _logger; - public WorkflowController(IPersistenceProvider persistenceStore, IDistributedLockProvider lockProvider, IWorkflowRegistry registry, IQueueProvider queueProvider, IExecutionPointerFactory pointerFactory, ILifeCycleEventHub eventHub, ILoggerFactory loggerFactory, IServiceProvider serviceProvider) + public WorkflowController(IPersistenceProvider persistenceStore, IDistributedLockProvider lockProvider, IWorkflowRegistry registry, IQueueProvider queueProvider, IExecutionPointerFactory pointerFactory, ILifeCycleEventHub eventHub, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowMiddlewareRunner middlewareRunner) { _persistenceStore = persistenceStore; _lockProvider = lockProvider; @@ -32,6 +33,7 @@ public WorkflowController(IPersistenceProvider persistenceStore, IDistributedLoc _pointerFactory = pointerFactory; _eventHub = eventHub; _serviceProvider = serviceProvider; + _middlewareRunner = middlewareRunner; _logger = loggerFactory.CreateLogger(); } @@ -45,7 +47,7 @@ public Task StartWorkflow(string workflowId, int? version, object data = return StartWorkflow(workflowId, version, data, reference); } - public Task StartWorkflow(string workflowId, TData data = null, string reference=null) + public Task StartWorkflow(string workflowId, TData data = null, string reference=null) where TData : class, new() { return StartWorkflow(workflowId, null, data, reference); @@ -83,6 +85,8 @@ public async Task StartWorkflow(string workflowId, int? version, wf.ExecutionPointers.Add(_pointerFactory.BuildGenesisPointer(def)); + await _middlewareRunner.RunPreMiddleware(wf, def); + string id = await _persistenceStore.CreateNewWorkflow(wf); await _queueProvider.QueueWork(id, QueueType.Workflow); await _queueProvider.QueueWork(id, QueueType.Index); @@ -230,4 +234,4 @@ public void RegisterWorkflow() _registry.RegisterWorkflow(wf); } } -} \ No newline at end of file +} diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index e557a2bb2..a70de87a2 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -22,10 +22,12 @@ public class WorkflowExecutor : IWorkflowExecutor private readonly ICancellationProcessor _cancellationProcessor; private readonly ILifeCycleEventPublisher _publisher; private readonly WorkflowOptions _options; + private readonly IStepExecutor _stepExecutor; + private readonly IWorkflowMiddlewareRunner _middlewareRunner; private IWorkflowHost Host => _serviceProvider.GetService(); - public WorkflowExecutor(IWorkflowRegistry registry, IServiceProvider serviceProvider, IScopeProvider scopeProvider, IDateTimeProvider datetimeProvider, IExecutionResultProcessor executionResultProcessor, ILifeCycleEventPublisher publisher, ICancellationProcessor cancellationProcessor, WorkflowOptions options, ILoggerFactory loggerFactory) + public WorkflowExecutor(IWorkflowRegistry registry, IServiceProvider serviceProvider, IScopeProvider scopeProvider, IDateTimeProvider datetimeProvider, IExecutionResultProcessor executionResultProcessor, ILifeCycleEventPublisher publisher, ICancellationProcessor cancellationProcessor, WorkflowOptions options, IWorkflowMiddlewareRunner middlewareRunner, IStepExecutor stepExecutor, ILoggerFactory loggerFactory) { _serviceProvider = serviceProvider; _scopeProvider = scopeProvider; @@ -36,6 +38,8 @@ public WorkflowExecutor(IWorkflowRegistry registry, IServiceProvider serviceProv _options = options; _logger = loggerFactory.CreateLogger(); _executionResultProcessor = executionResultProcessor; + _middlewareRunner = middlewareRunner; + _stepExecutor = stepExecutor; } public async Task Execute(WorkflowInstance workflow, CancellationToken cancellationToken = default) @@ -49,7 +53,7 @@ public async Task Execute(WorkflowInstance workflow, Can _logger.LogError("Workflow {0} version {1} is not registered", workflow.WorkflowDefinitionId, workflow.Version); return wfResult; } - + _cancellationProcessor.ProcessCancellations(workflow, def, wfResult); foreach (var pointer in exePointers) @@ -71,10 +75,10 @@ public async Task Execute(WorkflowInstance workflow, Can }); continue; } - + try { - if (!InitializeStep(workflow, step, wfResult, def, pointer)) + if (!InitializeStep(workflow, step, wfResult, def, pointer)) continue; await ExecuteStep(workflow, step, pointer, wfResult, def, cancellationToken); @@ -89,14 +93,14 @@ public async Task Execute(WorkflowInstance workflow, Can ErrorTime = _datetimeProvider.UtcNow, Message = ex.Message }); - + _executionResultProcessor.HandleStepException(workflow, def, pointer, step, ex); Host.ReportStepError(workflow, step, ex); } _cancellationProcessor.ProcessCancellations(workflow, def, wfResult); } ProcessAfterExecutionIteration(workflow, def, wfResult); - DetermineNextExecutionTime(workflow); + await DetermineNextExecutionTime(workflow, def); return wfResult; } @@ -147,7 +151,7 @@ private async Task ExecuteStep(WorkflowInstance workflow, WorkflowStep step, Exe Item = pointer.ContextItem, CancellationToken = cancellationToken }; - + using (var scope = _scopeProvider.CreateScope(context)) { _logger.LogDebug("Starting step {0} on workflow {1}", step.Name, workflow.Id); @@ -181,7 +185,7 @@ private async Task ExecuteStep(WorkflowInstance workflow, WorkflowStep step, Exe return; } - var result = await body.RunAsync(context); + var result = await _stepExecutor.ExecuteStep(context, body); if (result.Proceed) { @@ -205,7 +209,7 @@ private void ProcessAfterExecutionIteration(WorkflowInstance workflow, WorkflowD } } - private void DetermineNextExecutionTime(WorkflowInstance workflow) + private async Task DetermineNextExecutionTime(WorkflowInstance workflow, WorkflowDefinition def) { //TODO: move to own class workflow.NextExecution = null; @@ -229,9 +233,9 @@ private void DetermineNextExecutionTime(WorkflowInstance workflow) { foreach (var pointer in workflow.ExecutionPointers.Where(x => x.Active && (x.Children ?? new List()).Count > 0)) { - if (!workflow.ExecutionPointers.FindByScope(pointer.Id).All(x => x.EndTime.HasValue)) + if (!workflow.ExecutionPointers.FindByScope(pointer.Id).All(x => x.EndTime.HasValue)) continue; - + if (!pointer.SleepUntil.HasValue) { workflow.NextExecution = 0; @@ -243,11 +247,14 @@ private void DetermineNextExecutionTime(WorkflowInstance workflow) } } - if ((workflow.NextExecution != null) || (workflow.ExecutionPointers.Any(x => x.EndTime == null))) + if ((workflow.NextExecution != null) || (workflow.ExecutionPointers.Any(x => x.EndTime == null))) return; - + workflow.Status = WorkflowStatus.Complete; workflow.CompleteTime = _datetimeProvider.UtcNow; + + await _middlewareRunner.RunPostMiddleware(workflow, def); + _publisher.PublishNotification(new WorkflowCompleted() { EventTimeUtc = _datetimeProvider.UtcNow, @@ -257,6 +264,5 @@ private void DetermineNextExecutionTime(WorkflowInstance workflow) Version = workflow.Version }); } - } } diff --git a/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs b/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs new file mode 100644 index 000000000..6eb6968b8 --- /dev/null +++ b/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Services +{ + /// + public class WorkflowMiddlewareRunner : IWorkflowMiddlewareRunner + { + private static readonly WorkflowDelegate NoopWorkflowDelegate = () => Task.CompletedTask; + private readonly IEnumerable _middleware; + private readonly IServiceProvider _serviceProvider; + + public WorkflowMiddlewareRunner( + IEnumerable middleware, + IServiceProvider serviceProvider + ) + { + _middleware = middleware; + _serviceProvider = serviceProvider; + } + + + /// + /// Runs workflow-level middleware that is set to run at the + /// phase. Middleware will be run in the + /// order in which they were registered with DI with middleware declared earlier starting earlier and + /// completing later. + /// + /// The to run for. + /// The definition. + /// A task that will complete when all middleware has run. + public async Task RunPreMiddleware(WorkflowInstance workflow, WorkflowDefinition def) + { + var preMiddleware = _middleware + .Where(m => m.Phase == WorkflowMiddlewarePhase.PreWorkflow) + .ToArray(); + + await RunWorkflowMiddleware(workflow, preMiddleware); + } + + /// + /// Runs workflow-level middleware that is set to run at the + /// phase. Middleware will be run in the + /// order in which they were registered with DI with middleware declared earlier starting earlier and + /// completing later. + /// + /// The to run for. + /// The definition. + /// A task that will complete when all middleware has run. + public async Task RunPostMiddleware(WorkflowInstance workflow, WorkflowDefinition def) + { + var postMiddleware = _middleware + .Where(m => m.Phase == WorkflowMiddlewarePhase.PostWorkflow) + .ToArray(); + + try + { + await RunWorkflowMiddleware(workflow, postMiddleware); + } + catch (Exception exception) + { + // On error, determine which error handler to run and then run it + var errorHandlerType = def.OnPostMiddlewareError ?? typeof(IWorkflowMiddlewareErrorHandler); + using (var scope = _serviceProvider.CreateScope()) + { + var typeInstance = scope.ServiceProvider.GetService(errorHandlerType); + if (typeInstance != null && typeInstance is IWorkflowMiddlewareErrorHandler handler) + { + await handler.HandleAsync(exception); + } + } + } + } + + private static async Task RunWorkflowMiddleware( + WorkflowInstance workflow, + IEnumerable middlewareCollection + ) + { + // Build the middleware chain + var middlewareChain = middlewareCollection + .Reverse() + .Aggregate( + NoopWorkflowDelegate, + (previous, middleware) => () => middleware.HandleAsync(workflow, previous) + ); + + await middlewareChain(); + } + } +} diff --git a/src/samples/WorkflowCore.Sample19/FlakyConnectionParams.cs b/src/samples/WorkflowCore.Sample19/FlakyConnectionParams.cs new file mode 100644 index 000000000..0fda1a91f --- /dev/null +++ b/src/samples/WorkflowCore.Sample19/FlakyConnectionParams.cs @@ -0,0 +1,9 @@ +using System; + +namespace WorkflowCore.Sample19 +{ + public class FlakyConnectionParams : IDescriptiveWorkflowParams + { + public string Description { get; set; } + } +} diff --git a/src/samples/WorkflowCore.Sample19/FlakyConnectionWorkflow.cs b/src/samples/WorkflowCore.Sample19/FlakyConnectionWorkflow.cs new file mode 100644 index 000000000..a388930d2 --- /dev/null +++ b/src/samples/WorkflowCore.Sample19/FlakyConnectionWorkflow.cs @@ -0,0 +1,25 @@ +using WorkflowCore.Interface; +using WorkflowCore.Sample19.Steps; + +namespace WorkflowCore.Sample19 +{ + public class FlakyConnectionWorkflow : IWorkflow + { + public string Id => "flaky-sample"; + + public int Version => 1; + + public void Build(IWorkflowBuilder builder) + { + builder + .StartWith() + .Input(x => x.Message, _ => "Starting workflow") + + .Then() + .Input(x => x.SucceedAfterAttempts, _ => 3) + + .Then() + .Input(x => x.Message, _ => "Finishing workflow"); + } + } +} diff --git a/src/samples/WorkflowCore.Sample19/IDescriptiveWorkflowParams.cs b/src/samples/WorkflowCore.Sample19/IDescriptiveWorkflowParams.cs new file mode 100644 index 000000000..73bd26892 --- /dev/null +++ b/src/samples/WorkflowCore.Sample19/IDescriptiveWorkflowParams.cs @@ -0,0 +1,7 @@ +namespace WorkflowCore.Sample19 +{ + public interface IDescriptiveWorkflowParams + { + string Description { get; } + } +} diff --git a/src/samples/WorkflowCore.Sample19/Middleware/AddDescriptionWorkflowMiddleware.cs b/src/samples/WorkflowCore.Sample19/Middleware/AddDescriptionWorkflowMiddleware.cs new file mode 100644 index 000000000..8c6080c12 --- /dev/null +++ b/src/samples/WorkflowCore.Sample19/Middleware/AddDescriptionWorkflowMiddleware.cs @@ -0,0 +1,20 @@ +using System.Threading.Tasks; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Sample19.Middleware +{ + public class AddDescriptionWorkflowMiddleware : IWorkflowMiddleware + { + public WorkflowMiddlewarePhase Phase => WorkflowMiddlewarePhase.PreWorkflow; + public Task HandleAsync(WorkflowInstance workflow, WorkflowDelegate next) + { + if (workflow.Data is IDescriptiveWorkflowParams descriptiveParams) + { + workflow.Description = descriptiveParams.Description; + } + + return next(); + } + } +} diff --git a/src/samples/WorkflowCore.Sample19/Middleware/LogCorrelationStepMiddleware.cs b/src/samples/WorkflowCore.Sample19/Middleware/LogCorrelationStepMiddleware.cs new file mode 100644 index 000000000..38fefc362 --- /dev/null +++ b/src/samples/WorkflowCore.Sample19/Middleware/LogCorrelationStepMiddleware.cs @@ -0,0 +1,38 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Sample19.Middleware +{ + /// + /// Loosely based off this article: + /// https://www.frakkingsweet.com/net-core-log-correlation-easy-access-to-headers/ + /// + public class AddMetadataToLogsMiddleware: IWorkflowStepMiddleware + { + private readonly ILogger _log; + + public AddMetadataToLogsMiddleware(ILogger log) + { + _log = log; + } + + public async Task HandleAsync( + IStepExecutionContext context, + IStepBody body, + WorkflowStepDelegate next) + { + var workflowId = context.Workflow.Id; + var stepId = context.Step.Id; + + using (_log.BeginScope("WorkflowId => {@WorkflowId}", workflowId)) + using (_log.BeginScope("StepId => {@StepId}", stepId)) + { + return await next(); + } + } + } +} diff --git a/src/samples/WorkflowCore.Sample19/Middleware/PollyRetryMiddleware.cs b/src/samples/WorkflowCore.Sample19/Middleware/PollyRetryMiddleware.cs new file mode 100644 index 000000000..24e7621e7 --- /dev/null +++ b/src/samples/WorkflowCore.Sample19/Middleware/PollyRetryMiddleware.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Polly; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Sample19.Middleware +{ + public class PollyRetryMiddleware : IWorkflowStepMiddleware + { + private const string StepContextKey = "WorkflowStepContext"; + private const int MaxRetries = 3; + private readonly ILogger _log; + + public PollyRetryMiddleware(ILogger log) + { + _log = log; + } + + public IAsyncPolicy GetRetryPolicy() => + Policy + .Handle() + .RetryAsync( + MaxRetries, + (result, retryCount, context) => + UpdateRetryCount(result.Exception, retryCount, context[StepContextKey] as IStepExecutionContext) + ); + + public async Task HandleAsync( + IStepExecutionContext context, + IStepBody body, + WorkflowStepDelegate next + ) + { + return await GetRetryPolicy().ExecuteAsync(ctx => next(), new Dictionary + { + { StepContextKey, context } + }); + } + + private Task UpdateRetryCount( + Exception exception, + int retryCount, + IStepExecutionContext stepContext) + { + var stepInstance = stepContext.ExecutionPointer; + stepInstance.RetryCount = retryCount; + + _log.LogWarning( + exception, + "Exception occurred in step {StepId}. Retrying [{RetryCount}/{MaxCount}]", + stepInstance.Id, + retryCount, + MaxRetries + ); + + // TODO: Come up with way to persist workflow + return Task.CompletedTask; + } + } +} diff --git a/src/samples/WorkflowCore.Sample19/Middleware/PrintWorkflowSummaryMiddleware.cs b/src/samples/WorkflowCore.Sample19/Middleware/PrintWorkflowSummaryMiddleware.cs new file mode 100644 index 000000000..2cdba963e --- /dev/null +++ b/src/samples/WorkflowCore.Sample19/Middleware/PrintWorkflowSummaryMiddleware.cs @@ -0,0 +1,41 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Sample19.Middleware +{ + public class PrintWorkflowSummaryMiddleware : IWorkflowMiddleware + { + private readonly ILogger _log; + + public PrintWorkflowSummaryMiddleware(ILogger log) + { + _log = log; + } + + public WorkflowMiddlewarePhase Phase => WorkflowMiddlewarePhase.PostWorkflow; + + public Task HandleAsync(WorkflowInstance workflow, WorkflowDelegate next) + { + if (!workflow.CompleteTime.HasValue) + { + return next(); + } + + var duration = workflow.CompleteTime.Value - workflow.CreateTime; + _log.LogInformation($@"Workflow {workflow.Description} completed in {duration:g}"); + + foreach (var step in workflow.ExecutionPointers) + { + var stepName = step.StepName; + var stepDuration = (step.EndTime - step.StartTime) ?? TimeSpan.Zero; + _log.LogInformation($" - Step {stepName} completed in {stepDuration:g}"); + } + + return next(); + } + } +} diff --git a/src/samples/WorkflowCore.Sample19/Program.cs b/src/samples/WorkflowCore.Sample19/Program.cs new file mode 100644 index 000000000..1d6e38a48 --- /dev/null +++ b/src/samples/WorkflowCore.Sample19/Program.cs @@ -0,0 +1,66 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System; +using Microsoft.Extensions.Logging.Console; +using WorkflowCore.Interface; +using WorkflowCore.Sample19.Middleware; +using WorkflowCore.Sample19.Steps; + +namespace WorkflowCore.Sample19 +{ + class Program + { + static void Main(string[] args) + { + var serviceProvider = ConfigureServices(); + + // Start the workflow host + var host = serviceProvider.GetService(); + host.RegisterWorkflow(); + host.Start(); + + var workflowParams = new FlakyConnectionParams + { + Description = "Flaky connection workflow" + }; + var workflowId = host.StartWorkflow("flaky-sample", workflowParams).Result; + Console.WriteLine($"Kicked off workflow {workflowId}"); + + Console.ReadLine(); + host.Stop(); + } + + private static IServiceProvider ConfigureServices() + { + // Setup dependency injection + IServiceCollection services = new ServiceCollection(); + services.AddWorkflow(); + + // Add step middleware + // Note that middleware will get executed in the order in which they were registered + services.AddWorkflowStepMiddleware(); + services.AddWorkflowStepMiddleware(); + + // Add some pre workflow middleware + // This middleware will run before the workflow starts + services.AddWorkflowMiddleware(); + + // Add some post workflow middleware + // This middleware will run after the workflow completes + services.AddWorkflowMiddleware(); + + // Add workflow steps + services.AddTransient(); + services.AddTransient(); + + services.AddLogging(cfg => + { + cfg.AddConsole(x => x.IncludeScopes = true); + cfg.AddDebug(); + }); + + var serviceProvider = services.BuildServiceProvider(); + return serviceProvider; + } + } +} diff --git a/src/samples/WorkflowCore.Sample19/Steps/FlakyConnection.cs b/src/samples/WorkflowCore.Sample19/Steps/FlakyConnection.cs new file mode 100644 index 000000000..f04f33f11 --- /dev/null +++ b/src/samples/WorkflowCore.Sample19/Steps/FlakyConnection.cs @@ -0,0 +1,27 @@ +using System; +using System.Threading.Tasks; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Sample19.Steps +{ + public class FlakyConnection : StepBodyAsync + { + private static readonly TimeSpan Delay = TimeSpan.FromSeconds(1); + private int _currentCallCount = 0; + + public int? SucceedAfterAttempts { get; set; } = 3; + + public override async Task RunAsync(IStepExecutionContext context) + { + if (SucceedAfterAttempts.HasValue && _currentCallCount >= SucceedAfterAttempts.Value) + { + return ExecutionResult.Next(); + } + + _currentCallCount++; + await Task.Delay(Delay); + throw new TimeoutException("A call has timed out"); + } + } +} diff --git a/src/samples/WorkflowCore.Sample19/Steps/LogMessage.cs b/src/samples/WorkflowCore.Sample19/Steps/LogMessage.cs new file mode 100644 index 000000000..ac8f4b678 --- /dev/null +++ b/src/samples/WorkflowCore.Sample19/Steps/LogMessage.cs @@ -0,0 +1,29 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Sample19.Steps +{ + public class LogMessage : StepBodyAsync + { + private readonly ILogger _log; + + public LogMessage(ILogger log) + { + _log = log; + } + + public string Message { get; set; } + + public override Task RunAsync(IStepExecutionContext context) + { + if (Message != null) + { + _log.LogInformation(Message); + } + + return Task.FromResult(ExecutionResult.Next()); + } + } +} diff --git a/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj b/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj new file mode 100644 index 000000000..b2a7796c3 --- /dev/null +++ b/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj @@ -0,0 +1,20 @@ + + + + Exe + netcoreapp3.0 + + + + + + + + + + + + + + + diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/MiddlewareScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/MiddlewareScenario.cs new file mode 100644 index 000000000..1c6929209 --- /dev/null +++ b/test/WorkflowCore.IntegrationTests/Scenarios/MiddlewareScenario.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using WorkflowCore.Testing; +using Xunit; + +namespace WorkflowCore.IntegrationTests.Scenarios +{ + public class MiddlewareScenario : WorkflowTest + { + private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(60); + private static readonly TimeSpan Delay = TimeSpan.FromMilliseconds(5); + private readonly List _workflowMiddleware = new List(); + private readonly List _stepMiddleware = new List(); + private readonly TestStep _step = new TestStep(); + + public MiddlewareScenario() + { + Setup(); + } + + public TestWorkflowMiddleware[] PreMiddleware => _workflowMiddleware + .Where(x => x.Phase == WorkflowMiddlewarePhase.PreWorkflow) + .ToArray(); + + public TestWorkflowMiddleware[] PostMiddleware => _workflowMiddleware + .Where(x => x.Phase == WorkflowMiddlewarePhase.PostWorkflow) + .ToArray(); + + public class MyWorkflow: IWorkflow + { + public string Id => nameof(MyWorkflow); + + public int Version => 1; + + public void Build(IWorkflowBuilder builder) => + builder.StartWith(); + } + + public class TestStep : StepBodyAsync + { + + public DateTime? StartTime { get; private set; } + public DateTime? EndTime { get; private set; } + public bool HasCompleted => StartTime.HasValue && EndTime.HasValue; + + public override async Task RunAsync(IStepExecutionContext context) + { + StartTime = DateTime.UtcNow; + await Task.Delay(Delay); + EndTime = DateTime.UtcNow; + return ExecutionResult.Next(); + } + } + + public class TestWorkflowMiddleware : IWorkflowMiddleware + { + public TestWorkflowMiddleware(WorkflowMiddlewarePhase phase) + { + Phase = phase; + } + + public WorkflowMiddlewarePhase Phase { get; } + + public DateTime? StartTime { get; private set; } + public DateTime? EndTime { get; private set; } + public bool HasCompleted => StartTime.HasValue && EndTime.HasValue; + + public async Task HandleAsync(WorkflowInstance workflow, WorkflowDelegate next) + { + StartTime = DateTime.UtcNow; + await Task.Delay(Delay); + await next(); + await Task.Delay(Delay); + EndTime = DateTime.UtcNow; + } + } + + public class TestStepMiddleware : IWorkflowStepMiddleware + { + public DateTime? StartTime { get; private set; } + public DateTime? EndTime { get; private set; } + + public bool HasCompleted => StartTime.HasValue && EndTime.HasValue; + + public async Task HandleAsync(IStepExecutionContext context, IStepBody body, WorkflowStepDelegate next) + { + StartTime = DateTime.UtcNow; + await Task.Delay(Delay); + var result = await next(); + await Task.Delay(Delay); + EndTime = DateTime.UtcNow; + return result; + } + } + + protected override void ConfigureServices(IServiceCollection services) + { + base.ConfigureServices(services); + + services.AddTransient(_ => _step); + + // Configure 3 middleware of each type + const int middlewareCount = 3; + foreach (var _ in Enumerable.Range(0, middlewareCount)) + { + var preMiddleware = new TestWorkflowMiddleware(WorkflowMiddlewarePhase.PreWorkflow); + var postMiddleware = new TestWorkflowMiddleware(WorkflowMiddlewarePhase.PostWorkflow); + _workflowMiddleware.Add(preMiddleware); + _workflowMiddleware.Add(postMiddleware); + services.AddWorkflowMiddleware(p => preMiddleware); + services.AddWorkflowMiddleware(p => postMiddleware); + } + + // Configure 3 step middleware + foreach (var _ in Enumerable.Range(0, middlewareCount)) + { + var middleware = new TestStepMiddleware(); + services.AddWorkflowStepMiddleware(p => middleware); + _stepMiddleware.Add(middleware); + } + + } + + [Fact(DisplayName = "Should run all workflow and step middleware")] + public async Task Should_run_all_workflow_and_step_middleware() + { + var workflowId = await StartWorkflowAsync(new object()); + var status = await WaitForWorkflowToCompleteAsync(workflowId, Timeout); + + // Workflow should complete without errors + status.Should().Be(WorkflowStatus.Complete); + UnhandledStepErrors.Count.Should().Be(0); + + // Each middleware should have run + _workflowMiddleware.Should() + .HaveCount(6).And + .OnlyContain(x => x.HasCompleted); + _stepMiddleware.Should() + .HaveCount(3) + .And + .OnlyContain(x => x.HasCompleted); + + // Step middleware should have been run in order + _stepMiddleware.Should().BeInAscendingOrder(x => x.StartTime); + _stepMiddleware.Should().BeInDescendingOrder(x => x.EndTime); + + // Step should have been called after all step middleware + _step.HasCompleted.Should().BeTrue(); + _step.StartTime.Should().BeAfter(_stepMiddleware.Last().StartTime.Value); + _step.EndTime.Should().BeBefore(_stepMiddleware.Last().EndTime.Value); + + // Pre workflow middleware should have been run in order + PreMiddleware.Should().BeInAscendingOrder(x => x.StartTime); + PreMiddleware.Should().BeInDescendingOrder(x => x.EndTime); + + // Post workflow middleware should have been run in order + PostMiddleware.Should().BeInAscendingOrder(x => x.StartTime); + PostMiddleware.Should().BeInDescendingOrder(x => x.EndTime); + } + } +} diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs index fb7d2eed1..7d8a0117a 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs @@ -5,13 +5,14 @@ using WorkflowCore.Models; using Xunit; using FluentAssertions; +using WorkflowCore.Services.DefinitionStorage; using WorkflowCore.Testing; using WorkflowCore.TestAssets.DataTypes; namespace WorkflowCore.IntegrationTests.Scenarios { public class StoredJsonScenario : JsonWorkflowTest - { + { public StoredJsonScenario() { Setup(); diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs index 820f86bd8..3b37d2eb7 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs @@ -5,13 +5,14 @@ using WorkflowCore.Models; using Xunit; using FluentAssertions; +using WorkflowCore.Services.DefinitionStorage; using WorkflowCore.Testing; using WorkflowCore.TestAssets.DataTypes; namespace WorkflowCore.IntegrationTests.Scenarios { public class StoredYamlScenario : YamlWorkflowTest - { + { public StoredYamlScenario() { Setup(); diff --git a/test/WorkflowCore.TestAssets/LockProvider/DistributedLockProviderTests.cs b/test/WorkflowCore.TestAssets/LockProvider/DistributedLockProviderTests.cs index 7f1eebf1d..677fb511c 100644 --- a/test/WorkflowCore.TestAssets/LockProvider/DistributedLockProviderTests.cs +++ b/test/WorkflowCore.TestAssets/LockProvider/DistributedLockProviderTests.cs @@ -2,12 +2,13 @@ using System.Collections.Generic; using System.Text; using System.Threading; +using System.Threading.Tasks; using WorkflowCore.Interface; using FluentAssertions; using NUnit.Framework; namespace WorkflowCore.TestAssets.LockProvider -{ +{ public abstract class DistributedLockProviderTests { protected IDistributedLockProvider Subject; @@ -19,10 +20,10 @@ public void Setup() Subject.Start(); } - protected abstract IDistributedLockProvider CreateProvider(); + protected abstract IDistributedLockProvider CreateProvider(); [Test] - public async void AcquiresLock() + public async Task AcquiresLock() { const string lock1 = "lock1"; const string lock2 = "lock2"; @@ -34,7 +35,7 @@ public async void AcquiresLock() } [Test] - public async void DoesNotAcquireWhenLocked() + public async Task DoesNotAcquireWhenLocked() { const string lock1 = "lock1"; await Subject.AcquireLock(lock1, new CancellationToken()); @@ -45,7 +46,7 @@ public async void DoesNotAcquireWhenLocked() } [Test] - public async void ReleasesLock() + public async Task ReleasesLock() { const string lock1 = "lock1"; await Subject.AcquireLock(lock1, new CancellationToken()); diff --git a/test/WorkflowCore.TestAssets/stored-definition.json b/test/WorkflowCore.TestAssets/stored-definition.json index 56f36ac5e..1db3a9174 100644 --- a/test/WorkflowCore.TestAssets/stored-definition.json +++ b/test/WorkflowCore.TestAssets/stored-definition.json @@ -90,4 +90,4 @@ } ] -} \ No newline at end of file +} diff --git a/test/WorkflowCore.Testing/JsonWorkflowTest.cs b/test/WorkflowCore.Testing/JsonWorkflowTest.cs index 16fd7c232..760966a52 100644 --- a/test/WorkflowCore.Testing/JsonWorkflowTest.cs +++ b/test/WorkflowCore.Testing/JsonWorkflowTest.cs @@ -17,6 +17,7 @@ public abstract class JsonWorkflowTest : IDisposable protected IWorkflowHost Host; protected IPersistenceProvider PersistenceProvider; protected IDefinitionLoader DefinitionLoader; + protected IWorkflowRegistry Registry; protected List UnhandledStepErrors = new List(); protected virtual void Setup() @@ -34,6 +35,7 @@ protected virtual void Setup() PersistenceProvider = serviceProvider.GetService(); DefinitionLoader = serviceProvider.GetService(); + Registry = serviceProvider.GetService(); Host = serviceProvider.GetService(); Host.OnStepError += Host_OnStepError; Host.Start(); @@ -106,5 +108,5 @@ public void Dispose() Host.Stop(); } } - + } diff --git a/test/WorkflowCore.Testing/WorkflowTest.cs b/test/WorkflowCore.Testing/WorkflowTest.cs index 1a0dc8d81..f61d6be0a 100644 --- a/test/WorkflowCore.Testing/WorkflowTest.cs +++ b/test/WorkflowCore.Testing/WorkflowTest.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using WorkflowCore.Interface; @@ -18,7 +19,7 @@ public abstract class WorkflowTest : IDisposable protected IWorkflowHost Host; protected IPersistenceProvider PersistenceProvider; protected List UnhandledStepErrors = new List(); - + protected virtual void Setup() { //setup dependency injection @@ -61,6 +62,13 @@ public string StartWorkflow(TData data) return workflowId; } + public async Task StartWorkflowAsync(TData data) + { + var def = new TWorkflow(); + var workflowId = await Host.StartWorkflow(def.Id, data); + return workflowId; + } + protected void WaitForWorkflowToComplete(string workflowId, TimeSpan timeOut) { var status = GetStatus(workflowId); @@ -73,6 +81,20 @@ protected void WaitForWorkflowToComplete(string workflowId, TimeSpan timeOut) } } + protected async Task WaitForWorkflowToCompleteAsync(string workflowId, TimeSpan timeOut) + { + var status = GetStatus(workflowId); + var counter = 0; + while ((status == WorkflowStatus.Runnable) && (counter < (timeOut.TotalMilliseconds / 100))) + { + await Task.Delay(100); + counter++; + status = GetStatus(workflowId); + } + + return status; + } + protected IEnumerable GetActiveSubscriptons(string eventName, string eventKey) { return PersistenceProvider.GetSubscriptions(eventName, eventKey, DateTime.MaxValue).Result; diff --git a/test/WorkflowCore.Testing/YamlWorkflowTest.cs b/test/WorkflowCore.Testing/YamlWorkflowTest.cs index 58cbb3cad..b16d07a6d 100644 --- a/test/WorkflowCore.Testing/YamlWorkflowTest.cs +++ b/test/WorkflowCore.Testing/YamlWorkflowTest.cs @@ -17,6 +17,7 @@ public abstract class YamlWorkflowTest : IDisposable protected IWorkflowHost Host; protected IPersistenceProvider PersistenceProvider; protected IDefinitionLoader DefinitionLoader; + protected IWorkflowRegistry Registry; protected List UnhandledStepErrors = new List(); protected virtual void Setup() @@ -34,6 +35,7 @@ protected virtual void Setup() PersistenceProvider = serviceProvider.GetService(); DefinitionLoader = serviceProvider.GetService(); + Registry = serviceProvider.GetService(); Host = serviceProvider.GetService(); Host.OnStepError += Host_OnStepError; Host.Start(); @@ -106,5 +108,4 @@ public void Dispose() Host.Stop(); } } - } diff --git a/test/WorkflowCore.UnitTests/Services/StepExecutorTests.cs b/test/WorkflowCore.UnitTests/Services/StepExecutorTests.cs new file mode 100644 index 000000000..86d2bfcee --- /dev/null +++ b/test/WorkflowCore.UnitTests/Services/StepExecutorTests.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading.Tasks; +using FakeItEasy; +using FluentAssertions; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using WorkflowCore.Services; +using Xunit; +using Xunit.Abstractions; + +namespace WorkflowCore.UnitTests.Services +{ + public class StepExecutorTests + { + protected List Middleware { get; } + protected IStepBody Body { get; } + protected IStepExecutionContext Context { get; } + protected IStepExecutor Runner { get; } + protected ExecutionResult DummyResult { get; } = ExecutionResult.Persist(null); + protected ITestOutputHelper Out { get; } + + public StepExecutorTests(ITestOutputHelper output) + { + Middleware = new List(); + Body = A.Fake(); + Context = A.Fake(); + Out = output; + Runner = new StepExecutor(Middleware); + + A + .CallTo(() => Body.RunAsync(A._)) + .Invokes(() => Out.WriteLine("Called step body")) + .Returns(DummyResult); + } + + [Fact(DisplayName = "ExecuteStep should run step when no middleware")] + public async Task ExecuteStep_should_run_step_when_no_middleware() + { + // Act + var result = await Runner.ExecuteStep(Context, Body); + + // Assert + result.Should().Be(DummyResult); + } + + [Fact(DisplayName = "ExecuteStep should run middleware and step when one middleware")] + public async Task ExecuteStep_should_run_middleware_and_step_when_one_middleware() + { + // Arrange + var middleware = BuildStepMiddleware(); + Middleware.Add(middleware); + + // Act + var result = await Runner.ExecuteStep(Context, Body); + + // Assert + result.Should().Be(DummyResult); + A + .CallTo(RunMethodFor(Body)) + .MustHaveHappenedOnceExactly() + .Then( + A.CallTo(HandleMethodFor(middleware)) + .MustHaveHappenedOnceExactly()); + } + + [Fact(DisplayName = + "ExecuteStep should run middleware chain completing in reverse order and step when multiple middleware")] + public async Task + ExecuteStep_should_run_middleware_chain_completing_in_reverse_order_and_step_when_multiple_middleware() + { + // Arrange + var middleware1 = BuildStepMiddleware(1); + var middleware2 = BuildStepMiddleware(2); + var middleware3 = BuildStepMiddleware(3); + Middleware.AddRange(new[] { middleware1, middleware2, middleware3 }); + + // Act + var result = await Runner.ExecuteStep(Context, Body); + + // Assert + result.Should().Be(DummyResult); + A + .CallTo(RunMethodFor(Body)) + .MustHaveHappenedOnceExactly() + .Then(A + .CallTo(HandleMethodFor(middleware3)) + .MustHaveHappenedOnceExactly()) + .Then(A + .CallTo(HandleMethodFor(middleware2)) + .MustHaveHappenedOnceExactly()) + .Then(A + .CallTo(HandleMethodFor(middleware1)) + .MustHaveHappenedOnceExactly()); + } + + [Fact(DisplayName = "ExecuteStep should bubble up exceptions in middleware")] + public void ExecuteStep_should_bubble_up_exceptions_in_middleware() + { + // Arrange + var middleware1 = BuildStepMiddleware(1); + var middleware2 = BuildStepMiddleware(2); + var middleware3 = BuildStepMiddleware(3); + Middleware.AddRange(new[] { middleware1, middleware2, middleware3 }); + A + .CallTo(HandleMethodFor(middleware2)) + .Throws(new ApplicationException("Failed")); + + // Act + Func> action = async () => await Runner.ExecuteStep(Context, Body); + + // Assert + action + .ShouldThrow() + .WithMessage("Failed"); + } + + #region Helpers + + private IWorkflowStepMiddleware BuildStepMiddleware(int id = 0) + { + var middleware = A.Fake(); + A + .CallTo(HandleMethodFor(middleware)) + .ReturnsLazily(async call => + { + Out.WriteLine($@"Before step middleware {id}"); + var result = await call.Arguments[2].As().Invoke(); + Out.WriteLine($@"After step middleware {id}"); + return result; + }); + + return middleware; + } + + private static Expression>> HandleMethodFor(IWorkflowStepMiddleware middleware) => + () => middleware.HandleAsync( + A._, + A._, + A._); + + private static Expression>> RunMethodFor(IStepBody body) => + () => body.RunAsync(A._); + + #endregion + } +} diff --git a/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs b/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs index 622af03ff..8b6f22e22 100644 --- a/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs +++ b/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs @@ -3,6 +3,8 @@ using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; +using System.Threading.Tasks; +using FluentAssertions; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Services; @@ -22,6 +24,8 @@ public class WorkflowExecutorFixture protected IServiceProvider ServiceProvider; protected IScopeProvider ScopeProvider; protected IDateTimeProvider DateTimeProvider; + protected IStepExecutor StepExecutor; + protected IWorkflowMiddlewareRunner MiddlewareRunner; protected WorkflowOptions Options; public WorkflowExecutorFixture() @@ -35,6 +39,8 @@ public WorkflowExecutorFixture() EventHub = A.Fake(); CancellationProcessor = A.Fake(); DateTimeProvider = A.Fake(); + MiddlewareRunner = A.Fake(); + StepExecutor = A.Fake(); Options = new WorkflowOptions(A.Fake()); @@ -45,17 +51,26 @@ public WorkflowExecutorFixture() A.CallTo(() => DateTimeProvider.Now).Returns(DateTime.Now); A.CallTo(() => DateTimeProvider.UtcNow).Returns(DateTime.UtcNow); + A.CallTo(() => MiddlewareRunner + .RunPostMiddleware(A._, A._)) + .Returns(Task.CompletedTask); + + A.CallTo(() => StepExecutor.ExecuteStep(A._, A._)) + .ReturnsLazily(call => + call.Arguments[1].As().RunAsync( + call.Arguments[0].As())); + //config logging var loggerFactory = new LoggerFactory(); - //loggerFactory.AddConsole(LogLevel.Debug); + //loggerFactory.AddConsole(LogLevel.Debug); - Subject = new WorkflowExecutor(Registry, ServiceProvider, ScopeProvider, DateTimeProvider, ResultProcesser, EventHub, CancellationProcessor, Options, loggerFactory); + Subject = new WorkflowExecutor(Registry, ServiceProvider, ScopeProvider, DateTimeProvider, ResultProcesser, EventHub, CancellationProcessor, Options, MiddlewareRunner, StepExecutor, loggerFactory); } [Fact(DisplayName = "Should execute active step")] public void should_execute_active_step() { - //arrange + //arrange var step1Body = A.Fake(); A.CallTo(() => step1Body.RunAsync(A.Ignored)).Returns(ExecutionResult.Next()); WorkflowStep step1 = BuildFakeStep(step1Body); @@ -72,7 +87,7 @@ public void should_execute_active_step() { new ExecutionPointer() { Id = "1", Active = true, StepId = 0 } }) - }; + }; //act Subject.Execute(instance); @@ -85,7 +100,7 @@ public void should_execute_active_step() [Fact(DisplayName = "Should trigger step hooks")] public void should_trigger_step_hooks() { - //arrange + //arrange var step1Body = A.Fake(); A.CallTo(() => step1Body.RunAsync(A.Ignored)).Returns(ExecutionResult.Next()); WorkflowStep step1 = BuildFakeStep(step1Body); @@ -116,7 +131,7 @@ public void should_trigger_step_hooks() [Fact(DisplayName = "Should not execute inactive step")] public void should_not_execute_inactive_step() { - //arrange + //arrange var step1Body = A.Fake(); A.CallTo(() => step1Body.RunAsync(A.Ignored)).Returns(ExecutionResult.Next()); WorkflowStep step1 = BuildFakeStep(step1Body); @@ -134,7 +149,7 @@ public void should_not_execute_inactive_step() new ExecutionPointer() { Id = "1", Active = false, StepId = 0 } }) }; - + //act Subject.Execute(instance); @@ -148,7 +163,7 @@ public void should_map_inputs() //arrange var param = A.Fake(); - var step1Body = A.Fake(); + var step1Body = A.Fake(); A.CallTo(() => step1Body.RunAsync(A.Ignored)).Returns(ExecutionResult.Next()); WorkflowStep step1 = BuildFakeStep(step1Body, new List() { @@ -183,7 +198,7 @@ public void should_map_inputs() [Fact(DisplayName = "Should map outputs")] public void should_map_outputs() { - //arrange + //arrange var param = A.Fake(); var step1Body = A.Fake(); @@ -212,7 +227,7 @@ public void should_map_outputs() new ExecutionPointer() { Id = "1", Active = true, StepId = 0 } }) }; - + //act Subject.Execute(instance); @@ -221,12 +236,12 @@ public void should_map_outputs() .MustHaveHappened(); } - + [Fact(DisplayName = "Should handle step exception")] public void should_handle_step_exception() { - //arrange + //arrange var step1Body = A.Fake(); A.CallTo(() => step1Body.RunAsync(A.Ignored)).Throws(); WorkflowStep step1 = BuildFakeStep(step1Body); @@ -251,13 +266,13 @@ public void should_handle_step_exception() //assert A.CallTo(() => step1Body.RunAsync(A.Ignored)).MustHaveHappened(); A.CallTo(() => ResultProcesser.HandleStepException(instance, A.Ignored, A.Ignored, step1, A.Ignored)).MustHaveHappened(); - A.CallTo(() => ResultProcesser.ProcessExecutionResult(instance, A.Ignored, A.Ignored, step1, A.Ignored, A.Ignored)).MustNotHaveHappened(); + A.CallTo(() => ResultProcesser.ProcessExecutionResult(instance, A.Ignored, A.Ignored, step1, A.Ignored, A.Ignored)).MustNotHaveHappened(); } [Fact(DisplayName = "Should process after execution iteration")] public void should_process_after_execution_iteration() { - //arrange + //arrange var step1Body = A.Fake(); A.CallTo(() => step1Body.RunAsync(A.Ignored)).Returns(ExecutionResult.Persist(null)); WorkflowStep step1 = BuildFakeStep(step1Body); @@ -286,7 +301,7 @@ public void should_process_after_execution_iteration() [Fact(DisplayName = "Should process cancellations")] public void should_process_cancellations() { - //arrange + //arrange var step1Body = A.Fake(); A.CallTo(() => step1Body.RunAsync(A.Ignored)).Returns(ExecutionResult.Persist(null)); WorkflowStep step1 = BuildFakeStep(step1Body); diff --git a/test/WorkflowCore.UnitTests/Services/WorkflowMiddlewareRunnerTests.cs b/test/WorkflowCore.UnitTests/Services/WorkflowMiddlewareRunnerTests.cs new file mode 100644 index 000000000..991acfb23 --- /dev/null +++ b/test/WorkflowCore.UnitTests/Services/WorkflowMiddlewareRunnerTests.cs @@ -0,0 +1,276 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading.Tasks; +using FakeItEasy; +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using WorkflowCore.Services; +using Xunit; +using Xunit.Abstractions; + +namespace WorkflowCore.UnitTests.Services +{ + public class WorkflowMiddlewareRunnerTests + { + protected List Middleware { get; } + protected WorkflowInstance Workflow { get; } + protected WorkflowDefinition Definition { get; } + protected IServiceProvider ServiceProvider { get; } + protected IWorkflowMiddlewareErrorHandler TopLevelErrorHandler { get; } + protected IDefLevelErrorHandler DefLevelErrorHandler { get; } + protected IWorkflowMiddlewareRunner Runner { get; } + protected ITestOutputHelper Out { get; } + + public WorkflowMiddlewareRunnerTests(ITestOutputHelper output) + { + Out = output; + Middleware = new List(); + Workflow = new WorkflowInstance(); + Definition = new WorkflowDefinition(); + TopLevelErrorHandler = A.Fake(); + DefLevelErrorHandler = A.Fake(); + ServiceProvider = new ServiceCollection() + .AddTransient(_ => TopLevelErrorHandler) + .AddTransient(_ => DefLevelErrorHandler) + .BuildServiceProvider(); + + A + .CallTo(HandleMethodFor(TopLevelErrorHandler)) + .Returns(Task.CompletedTask); + A + .CallTo(HandleMethodFor(DefLevelErrorHandler)) + .Returns(Task.CompletedTask); + + Runner = new WorkflowMiddlewareRunner(Middleware, ServiceProvider); + } + + + [Fact(DisplayName = "RunPreMiddleware should run nothing when no middleware")] + public void RunPreMiddleware_should_run_nothing_when_no_middleware() + { + // Act + Func action = async () => await Runner.RunPreMiddleware(Workflow, Definition); + + // Assert + action.ShouldNotThrow(); + } + + [Fact(DisplayName = "RunPreMiddleware should run middleware when one middleware")] + public async Task RunPreMiddleware_should_run_middleware_when_one_middleware() + { + // Arrange + var middleware = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PreWorkflow); + Middleware.Add(middleware); + + // Act + await Runner.RunPreMiddleware(Workflow, Definition); + + // Assert + A + .CallTo(HandleMethodFor(middleware)) + .MustHaveHappenedOnceExactly(); + } + + [Fact(DisplayName = "RunPreMiddleware should run all middleware when multiple middleware")] + public async Task RunPreMiddleware_should_run_all_middleware_when_multiple_middleware() + { + // Arrange + var middleware1 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PreWorkflow, 1); + var middleware2 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PreWorkflow, 2); + var middleware3 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PreWorkflow, 3); + Middleware.AddRange(new[] { middleware1, middleware2, middleware3 }); + + // Act + await Runner.RunPreMiddleware(Workflow, Definition); + + // Assert + A + .CallTo(HandleMethodFor(middleware3)) + .MustHaveHappenedOnceExactly() + .Then(A + .CallTo(HandleMethodFor(middleware2)) + .MustHaveHappenedOnceExactly()) + .Then(A + .CallTo(HandleMethodFor(middleware1)) + .MustHaveHappenedOnceExactly()); + } + + [Fact(DisplayName = "RunPreMiddleware should only run middleware in PreWorkflow phase")] + public async Task RunPreMiddleware_should_only_run_middleware_in_PreWorkflow_phase() + { + // Arrange + var preMiddleware1 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PreWorkflow, 1); + var preMiddleware2 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PreWorkflow, 2); + var postMiddleware1 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PostWorkflow, 3); + var postMiddleware2 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PostWorkflow, 4); + Middleware.AddRange(new[] { postMiddleware1, postMiddleware2, preMiddleware1, preMiddleware2 }); + + // Act + await Runner.RunPreMiddleware(Workflow, Definition); + + // Assert + A + .CallTo(HandleMethodFor(preMiddleware2)) + .MustHaveHappenedOnceExactly() + .Then(A + .CallTo(HandleMethodFor(preMiddleware1)) + .MustHaveHappenedOnceExactly()); + + A.CallTo(HandleMethodFor(postMiddleware1)).MustNotHaveHappened(); + A.CallTo(HandleMethodFor(postMiddleware2)).MustNotHaveHappened(); + } + + [Fact(DisplayName = "RunPostMiddleware should run nothing when no middleware")] + public void RunPostMiddleware_should_run_nothing_when_no_middleware() + { + // Act + Func action = async () => await Runner.RunPostMiddleware(Workflow, Definition); + + // Assert + action.ShouldNotThrow(); + } + + [Fact(DisplayName = "RunPostMiddleware should run middleware when one middleware")] + public async Task RunPostMiddleware_should_run_middleware_when_one_middleware() + { + // Arrange + var middleware = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PostWorkflow); + Middleware.Add(middleware); + + // Act + await Runner.RunPostMiddleware(Workflow, Definition); + + // Assert + A + .CallTo(HandleMethodFor(middleware)) + .MustHaveHappenedOnceExactly(); + } + + [Fact(DisplayName = "RunPostMiddleware should run all middleware when multiple middleware")] + public async Task RunPostMiddleware_should_run_all_middleware_when_multiple_middleware() + { + // Arrange + var middleware1 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PostWorkflow, 1); + var middleware2 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PostWorkflow, 2); + var middleware3 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PostWorkflow, 3); + Middleware.AddRange(new[] { middleware1, middleware2, middleware3 }); + + // Act + await Runner.RunPostMiddleware(Workflow, Definition); + + // Assert + A + .CallTo(HandleMethodFor(middleware3)) + .MustHaveHappenedOnceExactly() + .Then(A + .CallTo(HandleMethodFor(middleware2)) + .MustHaveHappenedOnceExactly()) + .Then(A + .CallTo(HandleMethodFor(middleware1)) + .MustHaveHappenedOnceExactly()); + } + + [Fact(DisplayName = "RunPostMiddleware should only run middleware in PostWorkflow phase")] + public async Task RunPostMiddleware_should_only_run_middleware_in_PostWorkflow_phase() + { + // Arrange + var postMiddleware1 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PostWorkflow, 1); + var postMiddleware2 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PostWorkflow, 2); + var preMiddleware1 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PreWorkflow, 3); + var preMiddleware2 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PreWorkflow, 4); + Middleware.AddRange(new[] { preMiddleware1, postMiddleware1, preMiddleware2, postMiddleware2 }); + + // Act + await Runner.RunPostMiddleware(Workflow, Definition); + + // Assert + A + .CallTo(HandleMethodFor(postMiddleware2)) + .MustHaveHappenedOnceExactly() + .Then(A + .CallTo(HandleMethodFor(postMiddleware1)) + .MustHaveHappenedOnceExactly()); + + A.CallTo(HandleMethodFor(preMiddleware1)).MustNotHaveHappened(); + A.CallTo(HandleMethodFor(preMiddleware1)).MustNotHaveHappened(); + } + + [Fact(DisplayName = "RunPostMiddleware should call top level error handler when middleware throws")] + public async Task RunPostMiddleware_should_call_top_level_error_handler_when_middleware_throws() + { + // Arrange + var middleware = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PostWorkflow, 1); + A.CallTo(HandleMethodFor(middleware)).ThrowsAsync(new ApplicationException("Something went wrong")); + Middleware.AddRange(new[] { middleware }); + + // Act + await Runner.RunPostMiddleware(Workflow, Definition); + + // Assert + A + .CallTo(HandleMethodFor(TopLevelErrorHandler)) + .MustHaveHappenedOnceExactly(); + } + + [Fact(DisplayName = + "RunPostMiddleware should call error handler on workflow def when middleware throws and def has handler defined")] + public async Task + RunPostMiddleware_should_call_error_handler_on_workflow_def_when_middleware_throws_and_def_has_handler() + { + // Arrange + var middleware = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PostWorkflow, 1); + A.CallTo(HandleMethodFor(middleware)).ThrowsAsync(new ApplicationException("Something went wrong")); + Middleware.AddRange(new[] { middleware }); + Definition.OnPostMiddlewareError = typeof(IDefLevelErrorHandler); + + // Act + await Runner.RunPostMiddleware(Workflow, Definition); + + // Assert + A + .CallTo(HandleMethodFor(TopLevelErrorHandler)) + .MustNotHaveHappened(); + A + .CallTo(HandleMethodFor(DefLevelErrorHandler)) + .MustHaveHappenedOnceExactly(); + } + + #region Helpers + + private IWorkflowMiddleware BuildWorkflowMiddleware( + WorkflowMiddlewarePhase phase, + int id = 0 + ) + { + var middleware = A.Fake(); + A.CallTo(() => middleware.Phase).Returns(phase); + A + .CallTo(HandleMethodFor(middleware)) + .ReturnsLazily(async call => + { + Out.WriteLine($@"Before workflow middleware {id}"); + await call.Arguments[1].As().Invoke(); + Out.WriteLine($@"After workflow middleware {id}"); + }); + + return middleware; + } + + private static Expression> HandleMethodFor(IWorkflowMiddleware middleware) => + () => middleware.HandleAsync( + A._, + A._); + + private static Expression> HandleMethodFor(IWorkflowMiddlewareErrorHandler errorHandler) => + () => errorHandler.HandleAsync(A._); + + public interface IDefLevelErrorHandler : IWorkflowMiddlewareErrorHandler + { + } + + #endregion + } +} From 60314a46f1a822cbe1e8ec1ea9322a9cd451d33f Mon Sep 17 00:00:00 2001 From: DanilF Date: Sun, 1 Nov 2020 21:11:19 -0500 Subject: [PATCH 041/342] Fix race condition in MiddlewareScenario --- .../Scenarios/MiddlewareScenario.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/MiddlewareScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/MiddlewareScenario.cs index 1c6929209..530b94a58 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/MiddlewareScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/MiddlewareScenario.cs @@ -136,6 +136,12 @@ public async Task Should_run_all_workflow_and_step_middleware() // Workflow should complete without errors status.Should().Be(WorkflowStatus.Complete); UnhandledStepErrors.Count.Should().Be(0); + + // Wait for post middleware to complete + while (_workflowMiddleware.Any(x => !x.HasCompleted)) + { + await Task.Delay(500); + } // Each middleware should have run _workflowMiddleware.Should() From 499abf928d45f02525cfe5fb444e2fd982183fae Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Mon, 2 Nov 2020 17:57:51 -0800 Subject: [PATCH 042/342] bump version, release notes --- ReleaseNotes/3.3.0.md | 284 +++++++++++++++++++ src/WorkflowCore.DSL/WorkflowCore.DSL.csproj | 2 +- src/WorkflowCore/WorkflowCore.csproj | 8 +- 3 files changed, 289 insertions(+), 5 deletions(-) create mode 100644 ReleaseNotes/3.3.0.md diff --git a/ReleaseNotes/3.3.0.md b/ReleaseNotes/3.3.0.md new file mode 100644 index 000000000..da825c7ee --- /dev/null +++ b/ReleaseNotes/3.3.0.md @@ -0,0 +1,284 @@ +# Workflow Core 3.3.0 + +# Workflow Middleware + +Workflows can be extended with Middleware that run before/after workflows start/complete as well as around workflow steps to provide flexibility in implementing cross-cutting concerns such as [log correlation](https://www.frakkingsweet.com/net-core-log-correlation-easy-access-to-headers/), [retries](https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/implement-http-call-retries-exponential-backoff-polly), and other use-cases. + +This is done by implementing and registering `IWorkflowMiddleware` for workflows or `IWorkflowStepMiddleware` for steps. + +## Step Middleware + +Step middleware lets you run additional code around the execution of a given step and alter its behavior. Implementing a step middleware should look familiar to anyone familiar with [ASP.NET Core's middleware pipeline](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.1) or [`HttpClient`'s `DelegatingHandler` middleware](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1#outgoing-request-middleware). + +### Usage + +First, create your own middleware class that implements `IWorkflowStepMiddleware`. Here's an example of a middleware that adds workflow ID and step ID to the log correlation context of every workflow step in your app. + +**Important:** You must make sure to call `next()` as part of your middleware. If you do not do this, your step will never run. + +```cs +public class LogCorrelationStepMiddleware : IWorkflowStepMiddleware +{ + private readonly ILogger _log; + + public LogCorrelationStepMiddleware( + ILogger log) + { + _log = log; + } + + public async Task HandleAsync( + IStepExecutionContext context, + IStepBody body, + WorkflowStepDelegate next) + { + var workflowId = context.Workflow.Id; + var stepId = context.Step.Id; + + // Uses log scope to add a few attributes to the scope + using (_log.BeginScope("{@WorkflowId}", workflowId)) + using (_log.BeginScope("{@StepId}", stepId)) + { + // Calling next ensures step gets executed + return await next(); + } + } +} +``` + +Here's another example of a middleware that uses the [Polly](https://github.com/App-vNext/Polly) dotnet resiliency library to implement retries on workflow steps based off a custom retry policy. + +```cs +public class PollyRetryStepMiddleware : IWorkflowStepMiddleware +{ + private const string StepContextKey = "WorkflowStepContext"; + private const int MaxRetries = 3; + private readonly ILogger _log; + + public PollyRetryMiddleware(ILogger log) + { + _log = log; + } + + // Consult Polly's docs for more information on how to build + // retry policies: + // https://github.com/App-vNext/Polly + public IAsyncPolicy GetRetryPolicy() => + Policy + .Handle() + .RetryAsync( + MaxRetries, + (result, retryCount, context) => + UpdateRetryCount( + result.Exception, + retryCount, + context[StepContextKey] as IStepExecutionContext) + ); + + public async Task HandleAsync( + IStepExecutionContext context, + IStepBody body, + WorkflowStepDelegate next + ) + { + return await GetRetryPolicy().ExecuteAsync( + ctx => next(), + // The step execution context gets passed down so that + // the step is accessible within the retry policy + new Dictionary + { + { StepContextKey, context } + }); + } + + private Task UpdateRetryCount( + Exception exception, + int retryCount, + IStepExecutionContext stepContext) + { + var stepInstance = stepContext.ExecutionPointer; + stepInstance.RetryCount = retryCount; + return Task.CompletedTask; + } +} +``` + +## Pre/Post Workflow Middleware + +Workflow middleware run either before a workflow starts or after a workflow completes and can be used to hook into the workflow lifecycle or alter the workflow itself before it is started. + +### Pre Workflow Middleware + +These middleware get run before the workflow is started and can potentially alter properties on the `WorkflowInstance`. + +The following example illustrates setting the `Description` property on the `WorkflowInstance` using a middleware that interprets the data on the passed workflow. This is useful in cases where you want the description of the workflow to be derived from the data passed to the workflow. + +Note that you use `WorkflowMiddlewarePhase.PreWorkflow` to specify that it runs before the workflow starts. + +**Important:** You should call `next` as part of the workflow middleware to ensure that the next workflow in the chain runs. + +```cs +// AddDescriptionWorkflowMiddleware.cs +public class AddDescriptionWorkflowMiddleware : IWorkflowMiddleware +{ + public WorkflowMiddlewarePhase Phase => + WorkflowMiddlewarePhase.PreWorkflow; + + public Task HandleAsync( + WorkflowInstance workflow, + WorkflowDelegate next + ) + { + if (workflow.Data is IDescriptiveWorkflowParams descriptiveParams) + { + workflow.Description = descriptiveParams.Description; + } + + return next(); + } +} + +// IDescriptiveWorkflowParams.cs +public interface IDescriptiveWorkflowParams +{ + string Description { get; } +} + +// MyWorkflowParams.cs +public MyWorkflowParams : IDescriptiveWorkflowParams +{ + public string Description => $"Run task '{TaskName}'"; + + public string TaskName { get; set; } +} +``` + +### Exception Handling in Pre Workflow Middleware + +Pre workflow middleware exception handling gets treated differently from post workflow middleware. Since the middleware runs before the workflow starts, any exceptions thrown within a pre workflow middleware will bubble up to the `StartWorkflow` method and it is up to the caller of `StartWorkflow` to handle the exception and act accordingly. + +```cs +public async Task MyMethodThatStartsAWorkflow() +{ + try + { + await host.StartWorkflow("HelloWorld", 1, null); + } + catch(Exception ex) + { + // Handle the exception appropriately + } +} +``` + +### Post Workflow Middleware + +These middleware get run after the workflow has completed and can be used to perform additional actions for all workflows in your app. + +The following example illustrates how you can use a post workflow middleware to print a summary of the workflow to console. + +Note that you use `WorkflowMiddlewarePhase.PostWorkflow` to specify that it runs after the workflow completes. + +**Important:** You should call `next` as part of the workflow middleware to ensure that the next workflow in the chain runs. + +```cs +public class PrintWorkflowSummaryMiddleware : IWorkflowMiddleware +{ + private readonly ILogger _log; + + public PrintWorkflowSummaryMiddleware( + ILogger log + ) + { + _log = log; + } + + public WorkflowMiddlewarePhase Phase => + WorkflowMiddlewarePhase.PostWorkflow; + + public Task HandleAsync( + WorkflowInstance workflow, + WorkflowDelegate next + ) + { + if (!workflow.CompleteTime.HasValue) + { + return next(); + } + + var duration = workflow.CompleteTime.Value - workflow.CreateTime; + _log.LogInformation($@"Workflow {workflow.Description} completed in {duration:g}"); + + foreach (var step in workflow.ExecutionPointers) + { + var stepName = step.StepName; + var stepDuration = (step.EndTime - step.StartTime) ?? TimeSpan.Zero; + _log.LogInformation($" - Step {stepName} completed in {stepDuration:g}"); + } + + return next(); + } +} +``` + +### Exception Handling in Post Workflow Middleware + +Post workflow middleware exception handling gets treated differently from pre workflow middleware. At the time that the workflow completes, your workflow has ran already so an uncaught exception would be difficult to act on. + +By default, if a workflow middleware throws an exception, it will be logged and the workflow will complete as normal. This behavior can be changed, however. + +To override the default post workflow error handling for all workflows in your app, just register a new `IWorkflowMiddlewareErrorHandler` in the dependency injection framework with your custom behavior as follows. + +```cs +// CustomMiddlewareErrorHandler.cs +public class CustomHandler : IWorkflowMiddlewareErrorHandler +{ + public Task HandleAsync(Exception ex) + { + // Handle your error asynchronously + } +} + +// Startup.cs +public void ConfigureServices(IServiceCollection services) +{ + // Other workflow configuration + services.AddWorkflow(); + + // Should go after .AddWorkflow() + services.AddTransient(); +} +``` + +## Registering Middleware + +In order for middleware to take effect, they must be registered with the built-in dependency injection framework using the convenience helpers. + +**Note:** Middleware will be run in the order that they are registered with middleware that are registered earlier running earlier in the chain and finishing later in the chain. For pre/post workflow middleware, all pre middleware will be run before a workflow starts and all post middleware will be run after a workflow completes. + +```cs +public class Startup +{ + public void ConfigureServices(IServiceCollection services) + { + ... + + // Add workflow middleware + services.AddWorkflowMiddleware(); + services.AddWorkflowMiddleware(); + + // Add step middleware + services.AddWorkflowStepMiddleware(); + services.AddWorkflowStepMiddleware(); + + ... + } +} +``` + +## More Information + +See the [Workflow Middleware](https://github.com/danielgerlag/workflow-core/tree/master/src/samples/WorkflowCore.Sample19) sample for full examples of workflow middleware in action. + + +Many thanks to Danil Flores @dflor003 for this contribution! \ No newline at end of file diff --git a/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj b/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj index 913c643f4..3670d6553 100644 --- a/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj +++ b/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 3.1.5 + 3.3.0 DSL extenstion for Workflow Core provding support for JSON and YAML workflow definitions. Daniel Gerlag diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index c4ff1258a..3979b9139 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.2.6 - 3.2.6.0 - 3.2.6.0 + 3.3.0 + 3.3.0.0 + 3.3.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.2.6 + 3.3.0 From bf110e398d4c7fdeabbfbed7f6498080c0ea78fa Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 21 Nov 2020 08:10:08 -0800 Subject: [PATCH 043/342] issue 605 --- src/WorkflowCore/Services/WorkflowExecutor.cs | 23 ++++++++----------- src/WorkflowCore/WorkflowCore.csproj | 8 +++---- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index a70de87a2..b0987c27d 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -229,22 +229,19 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo workflow.NextExecution = Math.Min(pointerSleep, workflow.NextExecution ?? pointerSleep); } - if (workflow.NextExecution == null) + foreach (var pointer in workflow.ExecutionPointers.Where(x => x.Active && (x.Children ?? new List()).Count > 0)) { - foreach (var pointer in workflow.ExecutionPointers.Where(x => x.Active && (x.Children ?? new List()).Count > 0)) - { - if (!workflow.ExecutionPointers.FindByScope(pointer.Id).All(x => x.EndTime.HasValue)) - continue; - - if (!pointer.SleepUntil.HasValue) - { - workflow.NextExecution = 0; - return; - } + if (!workflow.ExecutionPointers.FindByScope(pointer.Id).All(x => x.EndTime.HasValue)) + continue; - var pointerSleep = pointer.SleepUntil.Value.ToUniversalTime().Ticks; - workflow.NextExecution = Math.Min(pointerSleep, workflow.NextExecution ?? pointerSleep); + if (!pointer.SleepUntil.HasValue) + { + workflow.NextExecution = 0; + return; } + + var pointerSleep = pointer.SleepUntil.Value.ToUniversalTime().Ticks; + workflow.NextExecution = Math.Min(pointerSleep, workflow.NextExecution ?? pointerSleep); } if ((workflow.NextExecution != null) || (workflow.ExecutionPointers.Any(x => x.EndTime == null))) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 3979b9139..8b9f2a080 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.3.0 - 3.3.0.0 - 3.3.0.0 + 3.3.1 + 3.3.1.0 + 3.3.1.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.3.0 + 3.3.1 From 687bf2350b1fe02920b856de009145fc61933534 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sun, 22 Nov 2020 13:32:51 -0800 Subject: [PATCH 044/342] ability to schedule execution pointers dependent another pointer completing first --- WorkflowCore.sln | 5 +++-- src/WorkflowCore/Models/ExecutionPointer.cs | 3 ++- .../Models/ExecutionPointerCollection.cs | 6 ++++++ .../Services/ErrorHandlers/CompensateHandler.cs | 16 +++++++++++++--- .../Services/ExecutionResultProcessor.cs | 10 ++++++++++ src/WorkflowCore/WorkflowCore.csproj | 8 ++++---- .../Scenarios/MultistepCompensationScenario.cs | 4 ++-- 7 files changed, 40 insertions(+), 12 deletions(-) diff --git a/WorkflowCore.sln b/WorkflowCore.sln index 09cda3de8..1ef2a187f 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -103,6 +103,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReleaseNotes", "ReleaseNote ReleaseNotes\2.1.2.md = ReleaseNotes\2.1.2.md ReleaseNotes\3.0.0.md = ReleaseNotes\3.0.0.md ReleaseNotes\3.1.0.md = ReleaseNotes\3.1.0.md + ReleaseNotes\3.3.0.md = ReleaseNotes\3.3.0.md EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample14", "src\samples\WorkflowCore.Sample14\WorkflowCore.Sample14.csproj", "{6BC66637-B42A-4334-ADFB-DBEC9F29D293}" @@ -145,9 +146,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample09s", "s EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScratchPad", "test\ScratchPad\ScratchPad.csproj", "{51BB7DCD-01DD-453D-A1E7-17E5E3DBB14C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Tests.QueueProviders.RabbitMQ", "test\WorkflowCore.Tests.QueueProviders.RabbitMQ\WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj", "{54DE20BA-EBA7-4BF0-9BD9-F03766849716}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Tests.QueueProviders.RabbitMQ", "test\WorkflowCore.Tests.QueueProviders.RabbitMQ\WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj", "{54DE20BA-EBA7-4BF0-9BD9-F03766849716}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Sample19", "src\samples\WorkflowCore.Sample19\WorkflowCore.Sample19.csproj", "{1223ED47-3E5E-4960-B70D-DFAF550F6666}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample19", "src\samples\WorkflowCore.Sample19\WorkflowCore.Sample19.csproj", "{1223ED47-3E5E-4960-B70D-DFAF550F6666}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/WorkflowCore/Models/ExecutionPointer.cs b/src/WorkflowCore/Models/ExecutionPointer.cs index 53938d76a..6c12afda7 100644 --- a/src/WorkflowCore/Models/ExecutionPointer.cs +++ b/src/WorkflowCore/Models/ExecutionPointer.cs @@ -63,6 +63,7 @@ public enum PointerStatus WaitingForEvent = 5, Failed = 6, Compensated = 7, - Cancelled = 8 + Cancelled = 8, + PendingPredecessor = 9 } } diff --git a/src/WorkflowCore/Models/ExecutionPointerCollection.cs b/src/WorkflowCore/Models/ExecutionPointerCollection.cs index a81e9fcf8..90e64348c 100644 --- a/src/WorkflowCore/Models/ExecutionPointerCollection.cs +++ b/src/WorkflowCore/Models/ExecutionPointerCollection.cs @@ -97,6 +97,12 @@ public ExecutionPointer Find(Predicate match) return _dictionary.Values.FirstOrDefault(x => match(x)); } + public ICollection FindByStatus(PointerStatus status) + { + //TODO: track states in hash table + return _dictionary.Values.Where(x => x.Status == status).ToList(); + } + public int Count => _dictionary.Count; public bool IsReadOnly => false; } diff --git a/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs index 12b62342a..2023a59f1 100644 --- a/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs @@ -63,11 +63,13 @@ public void Handle(WorkflowInstance workflow, WorkflowDefinition def, ExecutionP scopePointer.EndTime = _datetimeProvider.UtcNow; scopePointer.Status = PointerStatus.Failed; + ExecutionPointer compensationPointer = null; + if (scopeStep.CompensationStepId.HasValue) { scopePointer.Status = PointerStatus.Compensated; - var compensationPointer = _pointerFactory.BuildCompensationPointer(def, scopePointer, exceptionPointer, scopeStep.CompensationStepId.Value); + compensationPointer = _pointerFactory.BuildCompensationPointer(def, scopePointer, exceptionPointer, scopeStep.CompensationStepId.Value); workflow.ExecutionPointers.Add(compensationPointer); if (resume) @@ -89,8 +91,16 @@ public void Handle(WorkflowInstance workflow, WorkflowDefinition def, ExecutionP var siblingStep = def.Steps.FindById(siblingPointer.StepId); if (siblingStep.CompensationStepId.HasValue) { - var compensationPointer = _pointerFactory.BuildCompensationPointer(def, siblingPointer, exceptionPointer, siblingStep.CompensationStepId.Value); - workflow.ExecutionPointers.Add(compensationPointer); + var nextCompensationPointer = _pointerFactory.BuildCompensationPointer(def, siblingPointer, exceptionPointer, siblingStep.CompensationStepId.Value); + if (compensationPointer != null) + { + nextCompensationPointer.Active = false; + nextCompensationPointer.Status = PointerStatus.PendingPredecessor; + nextCompensationPointer.PredecessorId = compensationPointer.Id; + compensationPointer = nextCompensationPointer; + } + workflow.ExecutionPointers.Add(nextCompensationPointer); + siblingPointer.Status = PointerStatus.Compensated; } } diff --git a/src/WorkflowCore/Services/ExecutionResultProcessor.cs b/src/WorkflowCore/Services/ExecutionResultProcessor.cs index 448506823..781f3d39d 100755 --- a/src/WorkflowCore/Services/ExecutionResultProcessor.cs +++ b/src/WorkflowCore/Services/ExecutionResultProcessor.cs @@ -67,6 +67,16 @@ public void ProcessExecutionResult(WorkflowInstance workflow, WorkflowDefinition workflow.ExecutionPointers.Add(_pointerFactory.BuildNextPointer(def, pointer, outcomeTarget)); } + var pendingSubsequents = workflow.ExecutionPointers + .FindByStatus(PointerStatus.PendingPredecessor) + .Where(x => x.PredecessorId == pointer.Id); + + foreach (var subsequent in pendingSubsequents) + { + subsequent.Status = PointerStatus.Pending; + subsequent.Active = true; + } + _eventPublisher.PublishNotification(new StepCompleted() { EventTimeUtc = _datetimeProvider.UtcNow, diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 8b9f2a080..53cd19bcd 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.3.1 - 3.3.1.0 - 3.3.1.0 + 3.3.2 + 3.3.2.0 + 3.3.2.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.3.1 + 3.3.2 diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/MultistepCompensationScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/MultistepCompensationScenario.cs index 68fedfae9..afdbe588a 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/MultistepCompensationScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/MultistepCompensationScenario.cs @@ -34,11 +34,11 @@ public void Build(IWorkflowBuilder builder) Compensation1Fired = CompensationCounter; }) .Then(context => ExecutionResult.Next()) - .CompensateWith(context => + .CompensateWithSequence(context => context.StartWith(c => { CompensationCounter++; Compensation2Fired = CompensationCounter; - }) + })) .Then(context => ExecutionResult.Next()) .CompensateWith(context => { From 8593a5425dfe266dab46f88c6960a247fc49069e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=91=E9=9B=B60=E4=B8=83?= Date: Tue, 24 Nov 2020 15:15:37 +0800 Subject: [PATCH 045/342] add support for StepBodyAsync --- src/WorkflowCore.DSL/Services/DefinitionLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index 27d84492b..6acd6e33b 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -72,7 +72,7 @@ private WorkflowStepCollection ConvertSteps(ICollection source, Ty WorkflowStep targetStep; Type containerType; - if (stepType.IsSubclassOf(typeof(StepBody))) + if (stepType.GetInterfaces().Contains(typeof(IStepBody))) { containerType = typeof(WorkflowStep<>).MakeGenericType(stepType); From b1a0f42da4e7ff6894425de2acbd9e2fd6d9f299 Mon Sep 17 00:00:00 2001 From: Stephen Brown Date: Wed, 25 Nov 2020 18:00:15 +0100 Subject: [PATCH 046/342] Update to Entity Framework 5 --- src/WorkflowCore/WorkflowCore.csproj | 8 ++++---- .../WorkflowCore.Users/WorkflowCore.Users.csproj | 2 +- .../WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj | 2 +- ...WorkflowCore.Persistence.EntityFramework.csproj | 6 +++--- .../WorkflowCore.Persistence.MySQL.csproj | 6 +++--- .../WorkflowCore.Persistence.PostgreSQL.csproj | 8 ++++---- .../SqlServerContext.cs | 12 ++++++------ .../WorkflowCore.Persistence.SqlServer.csproj | 8 ++++---- .../WorkflowCore.Persistence.Sqlite.csproj | 4 ++-- .../WorkflowCore.Providers.AWS.csproj | 2 +- .../WorkflowCore.Providers.Elasticsearch.csproj | 2 +- .../WorkflowCore.Providers.Redis.csproj | 2 +- .../WorkflowCore.QueueProviders.SqlServer.csproj | 2 +- .../WorkflowCore.Sample01.csproj | 14 +++++++------- .../WorkflowCore.Sample02.csproj | 6 +++--- .../WorkflowCore.Sample03.csproj | 8 ++++---- .../WorkflowCore.Sample04.csproj | 8 ++++---- .../WorkflowCore.Sample05.csproj | 2 +- .../WorkflowCore.Sample06.csproj | 2 +- .../WorkflowCore.Sample07.csproj | 4 ++-- .../WorkflowCore.Sample08.csproj | 4 ++-- .../WorkflowCore.Sample09.csproj | 4 ++-- .../WorkflowCore.Sample09s.csproj | 6 +++--- .../WorkflowCore.Sample10.csproj | 4 ++-- .../WorkflowCore.Sample11.csproj | 6 +++--- .../WorkflowCore.Sample12.csproj | 4 ++-- .../WorkflowCore.Sample13.csproj | 4 ++-- .../WorkflowCore.Sample14.csproj | 2 +- .../WorkflowCore.Sample15.csproj | 6 +++--- .../WorkflowCore.Sample16.csproj | 6 +++--- .../WorkflowCore.Sample17.csproj | 4 ++-- .../WorkflowCore.Sample18.csproj | 12 ++++++------ .../WorkflowCore.Sample19.csproj | 12 ++++++------ .../WorkflowCore.TestSample01.csproj | 4 ++-- test/ScratchPad/ScratchPad.csproj | 6 +++--- .../WorkflowCore.IntegrationTests.csproj | 8 ++++---- .../WorkflowCore.TestAssets.csproj | 2 +- .../WorkflowCore.Testing.csproj | 6 +++--- .../WorkflowCore.Tests.DynamoDB.csproj | 2 +- .../WorkflowCore.Tests.Elasticsearch.csproj | 2 +- .../WorkflowCore.Tests.MongoDB.csproj | 8 ++++---- .../WorkflowCore.Tests.MySQL.csproj | 4 ++-- .../WorkflowCore.Tests.PostgreSQL.csproj | 4 ++-- .../WorkflowCore.Tests.Redis.csproj | 4 ++-- .../WorkflowCore.Tests.SqlServer.csproj | 2 +- .../WorkflowCore.Tests.Sqlite.csproj | 2 +- .../WorkflowCore.UnitTests.csproj | 8 ++++---- 47 files changed, 122 insertions(+), 122 deletions(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 53cd19bcd..0181a7bb7 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -25,10 +25,10 @@ - - - - + + + + diff --git a/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj b/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj index 5a8c0beab..dc124dcbe 100644 --- a/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj +++ b/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj @@ -25,7 +25,7 @@ - + diff --git a/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj b/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj index a3fb9bbb7..a8cb28cbd 100644 --- a/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj +++ b/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj @@ -25,7 +25,7 @@ - + diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index ed8392a62..712d77b86 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -3,7 +3,7 @@ Workflow Core EntityFramework Core Persistence Provider Daniel Gerlag - netstandard2.0 + netstandard2.1 WorkflowCore.Persistence.EntityFramework WorkflowCore.Persistence.EntityFramework workflow;.NET;Core;state machine;WorkflowCore;EntityFramework;EntityFrameworkCore @@ -26,8 +26,8 @@ - - + + diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index a031e5fba..0a8309e94 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -4,7 +4,7 @@ Workflow Core MySQL Persistence Provider 1.0.0 Daniel Gerlag - netstandard2.0 + netstandard2.1 WorkflowCore.Persistence.MySQL WorkflowCore.Persistence.MySQL workflow;.NET;Core;state machine;WorkflowCore;MySQL @@ -22,11 +22,11 @@ - + all runtime; build; native; contentfiles; analyzers - + diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index 7addc52a4..ade140ddd 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -27,12 +27,12 @@ - - - + + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs b/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs index 499c10295..7383cce3e 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs @@ -28,37 +28,37 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) protected override void ConfigureSubscriptionStorage(EntityTypeBuilder builder) { builder.ToTable("Subscription", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureWorkflowStorage(EntityTypeBuilder builder) { builder.ToTable("Workflow", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureExecutionPointerStorage(EntityTypeBuilder builder) { builder.ToTable("ExecutionPointer", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureExecutionErrorStorage(EntityTypeBuilder builder) { builder.ToTable("ExecutionError", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureExetensionAttributeStorage(EntityTypeBuilder builder) { builder.ToTable("ExtensionAttribute", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureEventStorage(EntityTypeBuilder builder) { builder.ToTable("Event", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } } } diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index be52279d1..f08ffcdfd 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -4,7 +4,7 @@ Workflow Core SQL Server Persistence Provider 1.8.0 Daniel Gerlag - netstandard2.0 + netstandard2.1 WorkflowCore.Persistence.SqlServer WorkflowCore.Persistence.SqlServer workflow;.NET;Core;state machine;WorkflowCore @@ -28,11 +28,11 @@ - - + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj index 2d2789021..6ad612e7a 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj +++ b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj @@ -4,7 +4,7 @@ Workflow Core Sqlite Persistence Provider 1.5.0 Daniel Gerlag - netstandard2.0 + netstandard2.1 WorkflowCore.Persistence.Sqlite WorkflowCore.Persistence.Sqlite workflow;.NET;Core;state machine;WorkflowCore;Sqlite @@ -28,7 +28,7 @@ - + diff --git a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj index 84eb6cb74..2be8582b5 100644 --- a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj +++ b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj b/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj index e4263abaf..29e44395b 100644 --- a/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj +++ b/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj b/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj index bdb8c6456..697d62fb3 100644 --- a/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj +++ b/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj index 36d7cda77..5abaea1a7 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj b/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj index e4a09e491..5f4857cca 100644 --- a/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj +++ b/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 WorkflowCore.Sample01 Exe WorkflowCore.Sample01 @@ -16,12 +16,12 @@ - - - - - - + + + + + + diff --git a/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj b/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj index 0765d50c3..7fab128b6 100644 --- a/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj +++ b/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 WorkflowCore.Sample02 Exe WorkflowCore.Sample02 @@ -11,8 +11,8 @@ - - + + diff --git a/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj b/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj index fc4a5d4fd..7b332dcd9 100644 --- a/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj +++ b/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp3.1 WorkflowCore.Sample03 Exe WorkflowCore.Sample03 @@ -16,9 +16,9 @@ - - - + + + diff --git a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj index 82107b0e6..af4dd01f9 100644 --- a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj +++ b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 WorkflowCore.Sample04 Exe WorkflowCore.Sample04 @@ -29,9 +29,9 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + diff --git a/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj b/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj index 592fa228b..069931ef0 100644 --- a/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj +++ b/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj b/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj index b61478b9e..d4c71d9aa 100644 --- a/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj +++ b/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj index 5ca51a866..2f5937f36 100644 --- a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj +++ b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 true WorkflowCore.Sample07 Exe @@ -26,7 +26,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj b/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj index 3ff429e28..2a556e45d 100644 --- a/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj +++ b/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 WorkflowCore.Sample08 Exe WorkflowCore.Sample08 @@ -21,7 +21,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj b/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj index 6f75a0d7d..bc16eb974 100644 --- a/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj +++ b/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.0 + netcoreapp3.1 - + diff --git a/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj b/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj index e569ec895..bc16eb974 100644 --- a/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj +++ b/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj @@ -1,12 +1,12 @@ - + Exe - netcoreapp3.0 + netcoreapp3.1 - + diff --git a/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj b/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj index 6f75a0d7d..bc16eb974 100644 --- a/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj +++ b/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.0 + netcoreapp3.1 - + diff --git a/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj b/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj index b6454f6a2..4eb65c992 100644 --- a/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj +++ b/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj @@ -2,12 +2,12 @@ Exe - netcoreapp2.2 + netcoreapp3.1 - - + + diff --git a/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj b/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj index 9879baab2..5b030fb75 100644 --- a/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj +++ b/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.0 + netcoreapp3.1 - + diff --git a/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj b/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj index dbe49166e..7f814f488 100644 --- a/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj +++ b/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp2.2 + netcoreapp3.1 - + diff --git a/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj b/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj index fef8173cc..974472a25 100644 --- a/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj +++ b/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.2 + netcoreapp3.1 diff --git a/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj b/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj index c63fbd792..9fd7656d7 100644 --- a/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj +++ b/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj @@ -2,12 +2,12 @@ Exe - netcoreapp2.2 + netcoreapp3.1 - - + + diff --git a/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj b/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj index c63fbd792..9fd7656d7 100644 --- a/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj +++ b/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj @@ -2,12 +2,12 @@ Exe - netcoreapp2.2 + netcoreapp3.1 - - + + diff --git a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj index 26933096d..0c1689366 100644 --- a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj +++ b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.0 + netcoreapp3.1 - + diff --git a/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj b/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj index 660b47511..46ad70bf5 100644 --- a/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj +++ b/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj @@ -1,15 +1,15 @@ - + Exe - netcoreapp3.0 + netcoreapp3.1 - - - - + + + + diff --git a/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj b/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj index b2a7796c3..f1fbd9c5c 100644 --- a/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj +++ b/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj @@ -1,15 +1,15 @@ - + Exe - netcoreapp3.0 + netcoreapp3.1 - - - - + + + + diff --git a/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj b/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj index 282fdbb15..789e6e445 100644 --- a/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj +++ b/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj @@ -1,12 +1,12 @@  - netcoreapp2.2 + netcoreapp3.1 - + diff --git a/test/ScratchPad/ScratchPad.csproj b/test/ScratchPad/ScratchPad.csproj index 4fb61dd24..27c262350 100644 --- a/test/ScratchPad/ScratchPad.csproj +++ b/test/ScratchPad/ScratchPad.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 ScratchPad Exe ScratchPad @@ -11,8 +11,8 @@ - - + + diff --git a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj index 971f10c57..8739a6c6d 100644 --- a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj +++ b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 WorkflowCore.IntegrationTests WorkflowCore.IntegrationTests true @@ -21,10 +21,10 @@ - - + + - + diff --git a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj index 12da1f57b..aeeb3d614 100644 --- a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj +++ b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 WorkflowCore.TestAssets WorkflowCore.TestAssets false diff --git a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj index 32f9c1363..8797551c8 100644 --- a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj +++ b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj index c2563b8b2..f275a05cf 100644 --- a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj +++ b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.1 false diff --git a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj index 168be514f..0ed01e311 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj +++ b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 false diff --git a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj index bec4d8561..cb4beac90 100644 --- a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj +++ b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 WorkflowCore.Tests.MongoDB WorkflowCore.Tests.MongoDB true @@ -22,9 +22,9 @@ - - - + + + diff --git a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj index a255e01d6..66a792fe5 100644 --- a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj +++ b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj @@ -1,7 +1,7 @@ - + - netcoreapp2.2 + netcoreapp3.1 false diff --git a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj index 1cc7d56bd..2fefbdea8 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj +++ b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 WorkflowCore.Tests.PostgreSQL WorkflowCore.Tests.PostgreSQL true @@ -21,7 +21,7 @@ - + diff --git a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj index c5ee9a6f8..76857bc6d 100644 --- a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj +++ b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj @@ -1,7 +1,7 @@ - + - netcoreapp2.2 + netcoreapp3.1 false diff --git a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj index 011714983..497293aaf 100644 --- a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj +++ b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 diff --git a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj index 9ce1b77cd..9598398f4 100644 --- a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj +++ b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 diff --git a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj index 294adbd23..bc8321631 100644 --- a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj +++ b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 WorkflowCore.UnitTests WorkflowCore.UnitTests true @@ -20,9 +20,9 @@ - - - + + + From f22ef4e36546f3dec5de7a62ca97a9ea8d66c0ae Mon Sep 17 00:00:00 2001 From: Stephen Brown Date: Tue, 1 Dec 2020 18:11:11 +0100 Subject: [PATCH 047/342] Increase minor versions for all dotnet5 affected packages, sync up EF related packages with the main version number --- src/WorkflowCore/WorkflowCore.csproj | 8 ++++---- .../WorkflowCore.Users/WorkflowCore.Users.csproj | 6 +++--- .../WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj | 2 +- .../WorkflowCore.Persistence.EntityFramework.csproj | 8 ++++---- .../WorkflowCore.Persistence.MySQL.csproj | 6 +++--- .../WorkflowCore.Persistence.PostgreSQL.csproj | 8 ++++---- .../WorkflowCore.Persistence.SqlServer.csproj | 8 ++++---- .../WorkflowCore.Persistence.Sqlite.csproj | 8 ++++---- .../WorkflowCore.Providers.AWS.csproj | 6 +++--- .../WorkflowCore.Providers.Elasticsearch.csproj | 2 +- .../WorkflowCore.Providers.Redis.csproj | 4 ++-- .../WorkflowCore.QueueProviders.SqlServer.csproj | 2 +- test/WorkflowCore.Testing/WorkflowCore.Testing.csproj | 6 +++--- 13 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 0181a7bb7..1da781981 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.3.2 - 3.3.2.0 - 3.3.2.0 + 3.3.3 + 3.3.3.0 + 3.3.3.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.3.2 + 3.3.3 diff --git a/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj b/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj index dc124dcbe..fb3a51fc3 100644 --- a/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj +++ b/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj @@ -15,9 +15,9 @@ false false Provides extensions for Workflow Core to enable human workflows. - 2.1.1 - 2.1.1.0 - 2.1.1.0 + 2.1.2 + 2.1.2.0 + 2.1.2.0 diff --git a/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj b/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj index a8cb28cbd..dbdec8e16 100644 --- a/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj +++ b/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj @@ -14,7 +14,7 @@ false false false - 2.0.0 + 2.0.1 WebAPI wrapper for Workflow host diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index 712d77b86..214787365 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -14,11 +14,11 @@ false false false - 3.1.0 + 3.3.3 Base package for Workflow-core peristence providers using entity framework - 3.1.0.0 - 3.1.0.0 - 3.1.0 + 3.3.3.0 + 3.3.3.0 + 3.3.3 diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index 0a8309e94..f1b09d045 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -16,9 +16,9 @@ false false Provides support to persist workflows running on Workflow Core to a MySQL database. - 3.0.1 - 3.0.1.0 - 3.0.1.0 + 3.3.3 + 3.3.3.0 + 3.3.3.0 diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index ade140ddd..a041d19b1 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -15,10 +15,10 @@ false false Provides support to persist workflows running on Workflow Core to a PostgreSQL database. - 3.1.0 - 3.1.0.0 - 3.1.0.0 - 3.1.0 + 3.3.3 + 3.3.3.0 + 3.3.3.0 + 3.3.3 diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index f08ffcdfd..427bbbdf3 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -15,11 +15,11 @@ false false false - 3.1.0 + 3.3.3 Provides support to persist workflows running on Workflow Core to a SQL Server database. - 3.1.0.0 - 3.1.0.0 - 3.1.0 + 3.3.3.0 + 3.3.3.0 + 3.3.3 diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj index 6ad612e7a..ddcc8deac 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj +++ b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj @@ -16,10 +16,10 @@ false false Provides support to persist workflows running on Workflow Core to a Sqlite database. - 3.1.0 - 3.1.0.0 - 3.1.0.0 - 3.1.0 + 3.3.3 + 3.3.3.0 + 3.3.3.0 + 3.3.3 diff --git a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj index 2be8582b5..b1da0b2fc 100644 --- a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj +++ b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj @@ -11,9 +11,9 @@ https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core.git git - 3.0.2 - 3.0.2.0 - 3.0.2 + 3.0.3 + 3.0.3.0 + 3.0.3 diff --git a/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj b/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj index 29e44395b..cf00e7d63 100644 --- a/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj +++ b/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 3.0.0 + 3.0.1 https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core.git diff --git a/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj b/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj index 697d62fb3..531435160 100644 --- a/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj +++ b/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj @@ -2,14 +2,14 @@ netstandard2.0 - 3.0.2 + 3.0.3 https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md https://github.com/danielgerlag/workflow-core.git git https://github.com/danielgerlag/workflow-core Redis providers for Workflow Core (Persistence, queueing, distributed locking and event hubs) - 3.0.2 + 3.0.3 diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj index 5abaea1a7..97b48d220 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj @@ -5,7 +5,7 @@ Roberto Paterlini Queue provider for Workflow-core using SQL Server Service Broker - 1.0.3-alpha + 1.0.4-alpha diff --git a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj index 8797551c8..981d713c4 100644 --- a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj +++ b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj @@ -2,9 +2,9 @@ netstandard2.0 - 2.3.0 - 2.3.0.0 - 2.3.0.0 + 2.3.1 + 2.3.1.0 + 2.3.1.0 Facilitates testing of workflows built on Workflow-Core From a96d7f618aac823b99a094aaf37102827449d187 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 2 Dec 2020 21:57:14 -0800 Subject: [PATCH 048/342] Revert "Update to Entity Framework 5" --- src/WorkflowCore/WorkflowCore.csproj | 16 ++++++++-------- .../WorkflowCore.Users/WorkflowCore.Users.csproj | 8 ++++---- .../WorkflowCore.WebAPI.csproj | 4 ++-- ...rkflowCore.Persistence.EntityFramework.csproj | 14 +++++++------- .../WorkflowCore.Persistence.MySQL.csproj | 12 ++++++------ .../WorkflowCore.Persistence.PostgreSQL.csproj | 16 ++++++++-------- .../SqlServerContext.cs | 12 ++++++------ .../WorkflowCore.Persistence.SqlServer.csproj | 16 ++++++++-------- .../WorkflowCore.Persistence.Sqlite.csproj | 12 ++++++------ .../WorkflowCore.Providers.AWS.csproj | 8 ++++---- .../WorkflowCore.Providers.Elasticsearch.csproj | 4 ++-- .../WorkflowCore.Providers.Redis.csproj | 6 +++--- .../WorkflowCore.QueueProviders.SqlServer.csproj | 4 ++-- .../WorkflowCore.Sample01.csproj | 14 +++++++------- .../WorkflowCore.Sample02.csproj | 6 +++--- .../WorkflowCore.Sample03.csproj | 8 ++++---- .../WorkflowCore.Sample04.csproj | 8 ++++---- .../WorkflowCore.Sample05.csproj | 2 +- .../WorkflowCore.Sample06.csproj | 2 +- .../WorkflowCore.Sample07.csproj | 4 ++-- .../WorkflowCore.Sample08.csproj | 4 ++-- .../WorkflowCore.Sample09.csproj | 4 ++-- .../WorkflowCore.Sample09s.csproj | 6 +++--- .../WorkflowCore.Sample10.csproj | 4 ++-- .../WorkflowCore.Sample11.csproj | 6 +++--- .../WorkflowCore.Sample12.csproj | 4 ++-- .../WorkflowCore.Sample13.csproj | 4 ++-- .../WorkflowCore.Sample14.csproj | 2 +- .../WorkflowCore.Sample15.csproj | 6 +++--- .../WorkflowCore.Sample16.csproj | 6 +++--- .../WorkflowCore.Sample17.csproj | 4 ++-- .../WorkflowCore.Sample18.csproj | 12 ++++++------ .../WorkflowCore.Sample19.csproj | 12 ++++++------ .../WorkflowCore.TestSample01.csproj | 4 ++-- test/ScratchPad/ScratchPad.csproj | 6 +++--- .../WorkflowCore.IntegrationTests.csproj | 8 ++++---- .../WorkflowCore.TestAssets.csproj | 2 +- .../WorkflowCore.Testing.csproj | 12 ++++++------ .../WorkflowCore.Tests.DynamoDB.csproj | 2 +- .../WorkflowCore.Tests.Elasticsearch.csproj | 2 +- .../WorkflowCore.Tests.MongoDB.csproj | 8 ++++---- .../WorkflowCore.Tests.MySQL.csproj | 4 ++-- .../WorkflowCore.Tests.PostgreSQL.csproj | 4 ++-- .../WorkflowCore.Tests.Redis.csproj | 4 ++-- .../WorkflowCore.Tests.SqlServer.csproj | 2 +- .../WorkflowCore.Tests.Sqlite.csproj | 2 +- .../WorkflowCore.UnitTests.csproj | 8 ++++---- 47 files changed, 159 insertions(+), 159 deletions(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 1da781981..53cd19bcd 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,20 +15,20 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.3.3 - 3.3.3.0 - 3.3.3.0 + 3.3.2 + 3.3.2.0 + 3.3.2.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.3.3 + 3.3.2 - - - - + + + + diff --git a/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj b/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj index fb3a51fc3..5a8c0beab 100644 --- a/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj +++ b/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj @@ -15,9 +15,9 @@ false false Provides extensions for Workflow Core to enable human workflows. - 2.1.2 - 2.1.2.0 - 2.1.2.0 + 2.1.1 + 2.1.1.0 + 2.1.1.0 @@ -25,7 +25,7 @@ - + diff --git a/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj b/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj index dbdec8e16..a3fb9bbb7 100644 --- a/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj +++ b/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj @@ -14,7 +14,7 @@ false false false - 2.0.1 + 2.0.0 WebAPI wrapper for Workflow host @@ -25,7 +25,7 @@ - + diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index 214787365..ed8392a62 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -3,7 +3,7 @@ Workflow Core EntityFramework Core Persistence Provider Daniel Gerlag - netstandard2.1 + netstandard2.0 WorkflowCore.Persistence.EntityFramework WorkflowCore.Persistence.EntityFramework workflow;.NET;Core;state machine;WorkflowCore;EntityFramework;EntityFrameworkCore @@ -14,11 +14,11 @@ false false false - 3.3.3 + 3.1.0 Base package for Workflow-core peristence providers using entity framework - 3.3.3.0 - 3.3.3.0 - 3.3.3 + 3.1.0.0 + 3.1.0.0 + 3.1.0 @@ -26,8 +26,8 @@ - - + + diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index f1b09d045..a031e5fba 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -4,7 +4,7 @@ Workflow Core MySQL Persistence Provider 1.0.0 Daniel Gerlag - netstandard2.1 + netstandard2.0 WorkflowCore.Persistence.MySQL WorkflowCore.Persistence.MySQL workflow;.NET;Core;state machine;WorkflowCore;MySQL @@ -16,17 +16,17 @@ false false Provides support to persist workflows running on Workflow Core to a MySQL database. - 3.3.3 - 3.3.3.0 - 3.3.3.0 + 3.0.1 + 3.0.1.0 + 3.0.1.0 - + all runtime; build; native; contentfiles; analyzers - + diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index a041d19b1..7addc52a4 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -15,10 +15,10 @@ false false Provides support to persist workflows running on Workflow Core to a PostgreSQL database. - 3.3.3 - 3.3.3.0 - 3.3.3.0 - 3.3.3 + 3.1.0 + 3.1.0.0 + 3.1.0.0 + 3.1.0 @@ -27,12 +27,12 @@ - - - + + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs b/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs index 7383cce3e..499c10295 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs @@ -28,37 +28,37 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) protected override void ConfigureSubscriptionStorage(EntityTypeBuilder builder) { builder.ToTable("Subscription", "wfc"); - builder.Property(x => x.PersistenceId).UseIdentityColumn(); + builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); } protected override void ConfigureWorkflowStorage(EntityTypeBuilder builder) { builder.ToTable("Workflow", "wfc"); - builder.Property(x => x.PersistenceId).UseIdentityColumn(); + builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); } protected override void ConfigureExecutionPointerStorage(EntityTypeBuilder builder) { builder.ToTable("ExecutionPointer", "wfc"); - builder.Property(x => x.PersistenceId).UseIdentityColumn(); + builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); } protected override void ConfigureExecutionErrorStorage(EntityTypeBuilder builder) { builder.ToTable("ExecutionError", "wfc"); - builder.Property(x => x.PersistenceId).UseIdentityColumn(); + builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); } protected override void ConfigureExetensionAttributeStorage(EntityTypeBuilder builder) { builder.ToTable("ExtensionAttribute", "wfc"); - builder.Property(x => x.PersistenceId).UseIdentityColumn(); + builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); } protected override void ConfigureEventStorage(EntityTypeBuilder builder) { builder.ToTable("Event", "wfc"); - builder.Property(x => x.PersistenceId).UseIdentityColumn(); + builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); } } } diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index 427bbbdf3..be52279d1 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -4,7 +4,7 @@ Workflow Core SQL Server Persistence Provider 1.8.0 Daniel Gerlag - netstandard2.1 + netstandard2.0 WorkflowCore.Persistence.SqlServer WorkflowCore.Persistence.SqlServer workflow;.NET;Core;state machine;WorkflowCore @@ -15,11 +15,11 @@ false false false - 3.3.3 + 3.1.0 Provides support to persist workflows running on Workflow Core to a SQL Server database. - 3.3.3.0 - 3.3.3.0 - 3.3.3 + 3.1.0.0 + 3.1.0.0 + 3.1.0 @@ -28,11 +28,11 @@ - - + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj index ddcc8deac..2d2789021 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj +++ b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj @@ -4,7 +4,7 @@ Workflow Core Sqlite Persistence Provider 1.5.0 Daniel Gerlag - netstandard2.1 + netstandard2.0 WorkflowCore.Persistence.Sqlite WorkflowCore.Persistence.Sqlite workflow;.NET;Core;state machine;WorkflowCore;Sqlite @@ -16,10 +16,10 @@ false false Provides support to persist workflows running on Workflow Core to a Sqlite database. - 3.3.3 - 3.3.3.0 - 3.3.3.0 - 3.3.3 + 3.1.0 + 3.1.0.0 + 3.1.0.0 + 3.1.0 @@ -28,7 +28,7 @@ - + diff --git a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj index b1da0b2fc..84eb6cb74 100644 --- a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj +++ b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj @@ -11,16 +11,16 @@ https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core.git git - 3.0.3 - 3.0.3.0 - 3.0.3 + 3.0.2 + 3.0.2.0 + 3.0.2 - + diff --git a/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj b/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj index cf00e7d63..e4263abaf 100644 --- a/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj +++ b/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 3.0.1 + 3.0.0 https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core.git @@ -13,7 +13,7 @@ - + diff --git a/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj b/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj index 531435160..bdb8c6456 100644 --- a/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj +++ b/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj @@ -2,18 +2,18 @@ netstandard2.0 - 3.0.3 + 3.0.2 https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md https://github.com/danielgerlag/workflow-core.git git https://github.com/danielgerlag/workflow-core Redis providers for Workflow Core (Persistence, queueing, distributed locking and event hubs) - 3.0.3 + 3.0.2 - + diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj index 97b48d220..36d7cda77 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj @@ -5,7 +5,7 @@ Roberto Paterlini Queue provider for Workflow-core using SQL Server Service Broker - 1.0.4-alpha + 1.0.3-alpha @@ -20,7 +20,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj b/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj index 5f4857cca..e4a09e491 100644 --- a/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj +++ b/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 WorkflowCore.Sample01 Exe WorkflowCore.Sample01 @@ -16,12 +16,12 @@ - - - - - - + + + + + + diff --git a/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj b/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj index 7fab128b6..0765d50c3 100644 --- a/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj +++ b/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 WorkflowCore.Sample02 Exe WorkflowCore.Sample02 @@ -11,8 +11,8 @@ - - + + diff --git a/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj b/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj index 7b332dcd9..fc4a5d4fd 100644 --- a/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj +++ b/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.0 WorkflowCore.Sample03 Exe WorkflowCore.Sample03 @@ -16,9 +16,9 @@ - - - + + + diff --git a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj index af4dd01f9..82107b0e6 100644 --- a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj +++ b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.0 WorkflowCore.Sample04 Exe WorkflowCore.Sample04 @@ -29,9 +29,9 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + diff --git a/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj b/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj index 069931ef0..592fa228b 100644 --- a/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj +++ b/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj b/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj index d4c71d9aa..b61478b9e 100644 --- a/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj +++ b/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj index 2f5937f36..5ca51a866 100644 --- a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj +++ b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.0 true WorkflowCore.Sample07 Exe @@ -26,7 +26,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj b/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj index 2a556e45d..3ff429e28 100644 --- a/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj +++ b/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.0 WorkflowCore.Sample08 Exe WorkflowCore.Sample08 @@ -21,7 +21,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj b/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj index bc16eb974..6f75a0d7d 100644 --- a/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj +++ b/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.1 + netcoreapp3.0 - + diff --git a/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj b/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj index bc16eb974..e569ec895 100644 --- a/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj +++ b/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj @@ -1,12 +1,12 @@ - + Exe - netcoreapp3.1 + netcoreapp3.0 - + diff --git a/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj b/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj index bc16eb974..6f75a0d7d 100644 --- a/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj +++ b/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.1 + netcoreapp3.0 - + diff --git a/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj b/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj index 4eb65c992..b6454f6a2 100644 --- a/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj +++ b/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj @@ -2,12 +2,12 @@ Exe - netcoreapp3.1 + netcoreapp2.2 - - + + diff --git a/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj b/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj index 5b030fb75..9879baab2 100644 --- a/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj +++ b/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.1 + netcoreapp3.0 - + diff --git a/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj b/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj index 7f814f488..dbe49166e 100644 --- a/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj +++ b/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.1 + netcoreapp2.2 - + diff --git a/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj b/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj index 974472a25..fef8173cc 100644 --- a/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj +++ b/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + netcoreapp2.2 diff --git a/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj b/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj index 9fd7656d7..c63fbd792 100644 --- a/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj +++ b/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj @@ -2,12 +2,12 @@ Exe - netcoreapp3.1 + netcoreapp2.2 - - + + diff --git a/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj b/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj index 9fd7656d7..c63fbd792 100644 --- a/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj +++ b/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj @@ -2,12 +2,12 @@ Exe - netcoreapp3.1 + netcoreapp2.2 - - + + diff --git a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj index 0c1689366..26933096d 100644 --- a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj +++ b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.1 + netcoreapp3.0 - + diff --git a/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj b/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj index 46ad70bf5..660b47511 100644 --- a/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj +++ b/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj @@ -1,15 +1,15 @@ - + Exe - netcoreapp3.1 + netcoreapp3.0 - - - - + + + + diff --git a/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj b/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj index f1fbd9c5c..b2a7796c3 100644 --- a/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj +++ b/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj @@ -1,15 +1,15 @@ - + Exe - netcoreapp3.1 + netcoreapp3.0 - - - - + + + + diff --git a/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj b/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj index 789e6e445..282fdbb15 100644 --- a/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj +++ b/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj @@ -1,12 +1,12 @@  - netcoreapp3.1 + netcoreapp2.2 - + diff --git a/test/ScratchPad/ScratchPad.csproj b/test/ScratchPad/ScratchPad.csproj index 27c262350..4fb61dd24 100644 --- a/test/ScratchPad/ScratchPad.csproj +++ b/test/ScratchPad/ScratchPad.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.0 ScratchPad Exe ScratchPad @@ -11,8 +11,8 @@ - - + + diff --git a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj index 8739a6c6d..971f10c57 100644 --- a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj +++ b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 WorkflowCore.IntegrationTests WorkflowCore.IntegrationTests true @@ -21,10 +21,10 @@ - - + + - + diff --git a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj index aeeb3d614..12da1f57b 100644 --- a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj +++ b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + netstandard2.0 WorkflowCore.TestAssets WorkflowCore.TestAssets false diff --git a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj index 981d713c4..32f9c1363 100644 --- a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj +++ b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj @@ -2,16 +2,16 @@ netstandard2.0 - 2.3.1 - 2.3.1.0 - 2.3.1.0 + 2.3.0 + 2.3.0.0 + 2.3.0.0 Facilitates testing of workflows built on Workflow-Core - - - + + + diff --git a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj index f275a05cf..c2563b8b2 100644 --- a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj +++ b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + netcoreapp2.2 false diff --git a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj index 0ed01e311..168be514f 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj +++ b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 false diff --git a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj index cb4beac90..bec4d8561 100644 --- a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj +++ b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 WorkflowCore.Tests.MongoDB WorkflowCore.Tests.MongoDB true @@ -22,9 +22,9 @@ - - - + + + diff --git a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj index 66a792fe5..a255e01d6 100644 --- a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj +++ b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1 + netcoreapp2.2 false diff --git a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj index 2fefbdea8..1cc7d56bd 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj +++ b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.0 WorkflowCore.Tests.PostgreSQL WorkflowCore.Tests.PostgreSQL true @@ -21,7 +21,7 @@ - + diff --git a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj index 76857bc6d..c5ee9a6f8 100644 --- a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj +++ b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1 + netcoreapp2.2 false diff --git a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj index 497293aaf..011714983 100644 --- a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj +++ b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 diff --git a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj index 9598398f4..9ce1b77cd 100644 --- a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj +++ b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 diff --git a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj index bc8321631..294adbd23 100644 --- a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj +++ b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 WorkflowCore.UnitTests WorkflowCore.UnitTests true @@ -20,9 +20,9 @@ - - - + + + From e73e1a46134b6f0fb216f2d3872e6c0c1ecabfdf Mon Sep 17 00:00:00 2001 From: glucaci Date: Thu, 3 Dec 2020 10:45:38 +0100 Subject: [PATCH 049/342] Add options to control which background task is starting --- src/WorkflowCore/Models/WorkflowOptions.cs | 5 ++++ .../ServiceCollectionExtensions.cs | 24 +++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/WorkflowCore/Models/WorkflowOptions.cs b/src/WorkflowCore/Models/WorkflowOptions.cs index 44f1f1375..f6e370283 100644 --- a/src/WorkflowCore/Models/WorkflowOptions.cs +++ b/src/WorkflowCore/Models/WorkflowOptions.cs @@ -34,6 +34,11 @@ public WorkflowOptions(IServiceCollection services) EventHubFactory = new Func(sp => new SingleNodeEventHub(sp.GetService())); } + public bool DisableWorkflowConsumer { get; set; } = false; + public bool DisableEventConsumer { get; set; } = false; + public bool DisableIndexConsumer { get; set; } = false; + public bool DisableRunnablePoller { get; set; } = false; + public void UsePersistence(Func factory) { PersistanceFactory = factory; diff --git a/src/WorkflowCore/ServiceCollectionExtensions.cs b/src/WorkflowCore/ServiceCollectionExtensions.cs index 8598abe03..d56b4484b 100644 --- a/src/WorkflowCore/ServiceCollectionExtensions.cs +++ b/src/WorkflowCore/ServiceCollectionExtensions.cs @@ -37,10 +37,26 @@ public static IServiceCollection AddWorkflow(this IServiceCollection services, A services.AddSingleton(options); services.AddSingleton(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + if (!options.DisableWorkflowConsumer) + { + services.AddTransient(); + } + + if (!options.DisableEventConsumer) + { + services.AddTransient(); + } + + if (!options.DisableIndexConsumer) + { + services.AddTransient(); + } + + if (!options.DisableRunnablePoller) + { + services.AddTransient(); + } + services.AddTransient(sp => sp.GetService()); services.AddTransient(); From 910974be6de8e1a046464c62eb9c5a170424db88 Mon Sep 17 00:00:00 2001 From: DanilF Date: Tue, 1 Dec 2020 16:43:30 -0500 Subject: [PATCH 050/342] Move WorkflowMiddlewareRunner and StepExecutor to be instantiated in a scope specific to the step to avoid potential threading issues when used with EFCore and DbContext --- src/WorkflowCore/ServiceCollectionExtensions.cs | 6 +++--- src/WorkflowCore/Services/WorkflowController.cs | 10 ++++++---- src/WorkflowCore/Services/WorkflowExecutor.cs | 15 ++++++++------- src/WorkflowCore/WorkflowCore.csproj | 8 ++++---- .../Services/WorkflowExecutorFixture.cs | 10 +++++++++- 5 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/WorkflowCore/ServiceCollectionExtensions.cs b/src/WorkflowCore/ServiceCollectionExtensions.cs index 8598abe03..bc15d0dd5 100644 --- a/src/WorkflowCore/ServiceCollectionExtensions.cs +++ b/src/WorkflowCore/ServiceCollectionExtensions.cs @@ -51,10 +51,10 @@ public static IServiceCollection AddWorkflow(this IServiceCollection services, A services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/src/WorkflowCore/Services/WorkflowController.cs b/src/WorkflowCore/Services/WorkflowController.cs index 20b7621d9..2a485c632 100755 --- a/src/WorkflowCore/Services/WorkflowController.cs +++ b/src/WorkflowCore/Services/WorkflowController.cs @@ -21,10 +21,9 @@ public class WorkflowController : IWorkflowController private readonly IExecutionPointerFactory _pointerFactory; private readonly ILifeCycleEventHub _eventHub; private readonly IServiceProvider _serviceProvider; - private readonly IWorkflowMiddlewareRunner _middlewareRunner; private readonly ILogger _logger; - public WorkflowController(IPersistenceProvider persistenceStore, IDistributedLockProvider lockProvider, IWorkflowRegistry registry, IQueueProvider queueProvider, IExecutionPointerFactory pointerFactory, ILifeCycleEventHub eventHub, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowMiddlewareRunner middlewareRunner) + public WorkflowController(IPersistenceProvider persistenceStore, IDistributedLockProvider lockProvider, IWorkflowRegistry registry, IQueueProvider queueProvider, IExecutionPointerFactory pointerFactory, ILifeCycleEventHub eventHub, ILoggerFactory loggerFactory, IServiceProvider serviceProvider) { _persistenceStore = persistenceStore; _lockProvider = lockProvider; @@ -33,7 +32,6 @@ public WorkflowController(IPersistenceProvider persistenceStore, IDistributedLoc _pointerFactory = pointerFactory; _eventHub = eventHub; _serviceProvider = serviceProvider; - _middlewareRunner = middlewareRunner; _logger = loggerFactory.CreateLogger(); } @@ -85,7 +83,11 @@ public async Task StartWorkflow(string workflowId, int? version, wf.ExecutionPointers.Add(_pointerFactory.BuildGenesisPointer(def)); - await _middlewareRunner.RunPreMiddleware(wf, def); + using (var scope = _serviceProvider.CreateScope()) + { + var middlewareRunner = scope.ServiceProvider.GetRequiredService(); + await middlewareRunner.RunPreMiddleware(wf, def); + } string id = await _persistenceStore.CreateNewWorkflow(wf); await _queueProvider.QueueWork(id, QueueType.Workflow); diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index b0987c27d..c6241fd64 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -22,12 +22,10 @@ public class WorkflowExecutor : IWorkflowExecutor private readonly ICancellationProcessor _cancellationProcessor; private readonly ILifeCycleEventPublisher _publisher; private readonly WorkflowOptions _options; - private readonly IStepExecutor _stepExecutor; - private readonly IWorkflowMiddlewareRunner _middlewareRunner; private IWorkflowHost Host => _serviceProvider.GetService(); - public WorkflowExecutor(IWorkflowRegistry registry, IServiceProvider serviceProvider, IScopeProvider scopeProvider, IDateTimeProvider datetimeProvider, IExecutionResultProcessor executionResultProcessor, ILifeCycleEventPublisher publisher, ICancellationProcessor cancellationProcessor, WorkflowOptions options, IWorkflowMiddlewareRunner middlewareRunner, IStepExecutor stepExecutor, ILoggerFactory loggerFactory) + public WorkflowExecutor(IWorkflowRegistry registry, IServiceProvider serviceProvider, IScopeProvider scopeProvider, IDateTimeProvider datetimeProvider, IExecutionResultProcessor executionResultProcessor, ILifeCycleEventPublisher publisher, ICancellationProcessor cancellationProcessor, WorkflowOptions options, ILoggerFactory loggerFactory) { _serviceProvider = serviceProvider; _scopeProvider = scopeProvider; @@ -38,8 +36,6 @@ public WorkflowExecutor(IWorkflowRegistry registry, IServiceProvider serviceProv _options = options; _logger = loggerFactory.CreateLogger(); _executionResultProcessor = executionResultProcessor; - _middlewareRunner = middlewareRunner; - _stepExecutor = stepExecutor; } public async Task Execute(WorkflowInstance workflow, CancellationToken cancellationToken = default) @@ -157,6 +153,7 @@ private async Task ExecuteStep(WorkflowInstance workflow, WorkflowStep step, Exe _logger.LogDebug("Starting step {0} on workflow {1}", step.Name, workflow.Id); IStepBody body = step.ConstructBody(scope.ServiceProvider); + var stepExecutor = scope.ServiceProvider.GetRequiredService(); if (body == null) { @@ -185,7 +182,7 @@ private async Task ExecuteStep(WorkflowInstance workflow, WorkflowStep step, Exe return; } - var result = await _stepExecutor.ExecuteStep(context, body); + var result = await stepExecutor.ExecuteStep(context, body); if (result.Proceed) { @@ -250,7 +247,11 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo workflow.Status = WorkflowStatus.Complete; workflow.CompleteTime = _datetimeProvider.UtcNow; - await _middlewareRunner.RunPostMiddleware(workflow, def); + using (var scope = _serviceProvider.CreateScope()) + { + var middlewareRunner = scope.ServiceProvider.GetRequiredService(); + await middlewareRunner.RunPostMiddleware(workflow, def); + } _publisher.PublishNotification(new WorkflowCompleted() { diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 53cd19bcd..36e9f45c1 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.3.2 - 3.3.2.0 - 3.3.2.0 + 3.3.3 + 3.3.3.0 + 3.3.3.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.3.2 + 3.3.3 diff --git a/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs b/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs index 8b6f22e22..cefaf9a23 100644 --- a/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs +++ b/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs @@ -51,6 +51,14 @@ public WorkflowExecutorFixture() A.CallTo(() => DateTimeProvider.Now).Returns(DateTime.Now); A.CallTo(() => DateTimeProvider.UtcNow).Returns(DateTime.UtcNow); + A + .CallTo(() => ServiceProvider.GetService(typeof(IWorkflowMiddlewareRunner))) + .Returns(MiddlewareRunner); + + A + .CallTo(() => ServiceProvider.GetService(typeof(IStepExecutor))) + .Returns(StepExecutor); + A.CallTo(() => MiddlewareRunner .RunPostMiddleware(A._, A._)) .Returns(Task.CompletedTask); @@ -64,7 +72,7 @@ public WorkflowExecutorFixture() var loggerFactory = new LoggerFactory(); //loggerFactory.AddConsole(LogLevel.Debug); - Subject = new WorkflowExecutor(Registry, ServiceProvider, ScopeProvider, DateTimeProvider, ResultProcesser, EventHub, CancellationProcessor, Options, MiddlewareRunner, StepExecutor, loggerFactory); + Subject = new WorkflowExecutor(Registry, ServiceProvider, ScopeProvider, DateTimeProvider, ResultProcesser, EventHub, CancellationProcessor, Options, loggerFactory); } [Fact(DisplayName = "Should execute active step")] From 3e72d297e0b29cd2cddcc8450b911da4918d2914 Mon Sep 17 00:00:00 2001 From: Dzianis Dziarkach Date: Thu, 10 Dec 2020 11:44:48 +0300 Subject: [PATCH 051/342] added DateTimeProvider to usages #issue-721 --- src/WorkflowCore/Services/ActivityController.cs | 4 ++-- .../Services/BackgroundTasks/RunnablePoller.cs | 8 +++++--- .../Services/CancellationProcessor.cs | 8 +++++--- src/WorkflowCore/Services/GreyList.cs | 8 +++++--- src/WorkflowCore/Services/SyncWorkflowRunner.cs | 6 ++++-- src/WorkflowCore/Services/WorkflowController.cs | 16 +++++++++------- .../ServiceCollectionExtensions.cs | 4 ++-- .../Services/DynamoLockProvider.cs | 10 ++++++---- .../Services/KinesisStreamConsumer.cs | 8 +++++--- .../Services/RedisPersistenceProvider.cs | 2 +- 10 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/WorkflowCore/Services/ActivityController.cs b/src/WorkflowCore/Services/ActivityController.cs index e8d1d727b..f39bb64b2 100644 --- a/src/WorkflowCore/Services/ActivityController.cs +++ b/src/WorkflowCore/Services/ActivityController.cs @@ -28,10 +28,10 @@ public ActivityController(ISubscriptionRepository subscriptionRepository, IWorkf public async Task GetPendingActivity(string activityName, string workerId, TimeSpan? timeout = null) { - var endTime = DateTime.UtcNow.Add(timeout ?? TimeSpan.Zero); + var endTime = _dateTimeProvider.UtcNow.Add(timeout ?? TimeSpan.Zero); var firstPass = true; EventSubscription subscription = null; - while ((subscription == null && DateTime.UtcNow < endTime) || firstPass) + while ((subscription == null && _dateTimeProvider.UtcNow < endTime) || firstPass) { if (!firstPass) await Task.Delay(100); diff --git a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs index 0800fe582..6a6bdf79c 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs @@ -15,15 +15,17 @@ internal class RunnablePoller : IBackgroundTask private readonly ILogger _logger; private readonly IGreyList _greylist; private readonly WorkflowOptions _options; + private readonly IDateTimeProvider _dateTimeProvider; private Timer _pollTimer; - public RunnablePoller(IPersistenceProvider persistenceStore, IQueueProvider queueProvider, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowRegistry registry, IDistributedLockProvider lockProvider, IGreyList greylist, WorkflowOptions options) + public RunnablePoller(IPersistenceProvider persistenceStore, IQueueProvider queueProvider, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowRegistry registry, IDistributedLockProvider lockProvider, IGreyList greylist, IDateTimeProvider dateTimeProvider, WorkflowOptions options) { _persistenceStore = persistenceStore; _greylist = greylist; _queueProvider = queueProvider; _logger = loggerFactory.CreateLogger(); _lockProvider = lockProvider; + _dateTimeProvider = dateTimeProvider; _options = options; } @@ -54,7 +56,7 @@ private async void PollRunnables(object target) try { _logger.LogInformation("Polling for runnable workflows"); - var runnables = await _persistenceStore.GetRunnableInstances(DateTime.Now); + var runnables = await _persistenceStore.GetRunnableInstances(_dateTimeProvider.Now); foreach (var item in runnables) { if (_greylist.Contains($"wf:{item}")) @@ -85,7 +87,7 @@ private async void PollRunnables(object target) try { _logger.LogInformation("Polling for unprocessed events"); - var events = await _persistenceStore.GetRunnableEvents(DateTime.Now); + var events = await _persistenceStore.GetRunnableEvents(_dateTimeProvider.Now); foreach (var item in events.ToList()) { if (_greylist.Contains($"evt:{item}")) diff --git a/src/WorkflowCore/Services/CancellationProcessor.cs b/src/WorkflowCore/Services/CancellationProcessor.cs index 74c7a8a60..3ee58e287 100644 --- a/src/WorkflowCore/Services/CancellationProcessor.cs +++ b/src/WorkflowCore/Services/CancellationProcessor.cs @@ -12,11 +12,13 @@ public class CancellationProcessor : ICancellationProcessor { protected readonly ILogger _logger; private readonly IExecutionResultProcessor _executionResultProcessor; + private readonly IDateTimeProvider _dateTimeProvider; - public CancellationProcessor(IExecutionResultProcessor executionResultProcessor, ILoggerFactory logFactory) + public CancellationProcessor(IExecutionResultProcessor executionResultProcessor, ILoggerFactory logFactory, IDateTimeProvider dateTimeProvider) { _executionResultProcessor = executionResultProcessor; _logger = logFactory.CreateLogger(); + _dateTimeProvider = dateTimeProvider; } public void ProcessCancellations(WorkflowInstance workflow, WorkflowDefinition workflowDef, WorkflowExecutorResult executionResult) @@ -44,13 +46,13 @@ public void ProcessCancellations(WorkflowInstance workflow, WorkflowDefinition w _executionResultProcessor.ProcessExecutionResult(workflow, workflowDef, ptr, step, ExecutionResult.Next(), executionResult); } - ptr.EndTime = DateTime.Now.ToUniversalTime(); + ptr.EndTime = _dateTimeProvider.UtcNow; ptr.Active = false; ptr.Status = PointerStatus.Cancelled; foreach (var descendent in workflow.ExecutionPointers.FindByScope(ptr.Id).Where(x => x.Status != PointerStatus.Complete && x.Status != PointerStatus.Cancelled)) { - descendent.EndTime = DateTime.Now.ToUniversalTime(); + descendent.EndTime = _dateTimeProvider.UtcNow; descendent.Active = false; descendent.Status = PointerStatus.Cancelled; } diff --git a/src/WorkflowCore/Services/GreyList.cs b/src/WorkflowCore/Services/GreyList.cs index ec1148291..85b67fbc8 100644 --- a/src/WorkflowCore/Services/GreyList.cs +++ b/src/WorkflowCore/Services/GreyList.cs @@ -11,19 +11,21 @@ public class GreyList : IGreyList, IDisposable private readonly Timer _cycleTimer; private readonly ConcurrentDictionary _list; private readonly ILogger _logger; + private readonly IDateTimeProvider _dateTimeProvider; private const int CYCLE_TIME = 30; private const int TTL = 5; - public GreyList(ILoggerFactory loggerFactory) + public GreyList(ILoggerFactory loggerFactory, IDateTimeProvider dateTimeProvider) { _logger = loggerFactory.CreateLogger(); + _dateTimeProvider = dateTimeProvider; _list = new ConcurrentDictionary(); _cycleTimer = new Timer(new TimerCallback(Cycle), null, TimeSpan.FromMinutes(CYCLE_TIME), TimeSpan.FromMinutes(CYCLE_TIME)); } public void Add(string id) { - _list.AddOrUpdate(id, DateTime.Now, (key, val) => DateTime.Now); + _list.AddOrUpdate(id, _dateTimeProvider.Now, (key, val) => _dateTimeProvider.Now); } public bool Contains(string id) @@ -31,7 +33,7 @@ public bool Contains(string id) if (!_list.TryGetValue(id, out var start)) return false; - var result = start > (DateTime.Now.AddMinutes(-1 * TTL)); + var result = start > (_dateTimeProvider.Now.AddMinutes(-1 * TTL)); if (!result) _list.TryRemove(id, out var _); diff --git a/src/WorkflowCore/Services/SyncWorkflowRunner.cs b/src/WorkflowCore/Services/SyncWorkflowRunner.cs index ab1b84469..65bf6c626 100644 --- a/src/WorkflowCore/Services/SyncWorkflowRunner.cs +++ b/src/WorkflowCore/Services/SyncWorkflowRunner.cs @@ -18,8 +18,9 @@ public class SyncWorkflowRunner : ISyncWorkflowRunner private readonly IPersistenceProvider _persistenceStore; private readonly IExecutionPointerFactory _pointerFactory; private readonly IQueueProvider _queueService; + private readonly IDateTimeProvider _dateTimeProvider; - public SyncWorkflowRunner(IWorkflowHost host, IWorkflowExecutor executor, IDistributedLockProvider lockService, IWorkflowRegistry registry, IPersistenceProvider persistenceStore, IExecutionPointerFactory pointerFactory, IQueueProvider queueService) + public SyncWorkflowRunner(IWorkflowHost host, IWorkflowExecutor executor, IDistributedLockProvider lockService, IWorkflowRegistry registry, IPersistenceProvider persistenceStore, IExecutionPointerFactory pointerFactory, IQueueProvider queueService, IDateTimeProvider dateTimeProvider) { _host = host; _executor = executor; @@ -28,6 +29,7 @@ public SyncWorkflowRunner(IWorkflowHost host, IWorkflowExecutor executor, IDistr _persistenceStore = persistenceStore; _pointerFactory = pointerFactory; _queueService = queueService; + _dateTimeProvider = dateTimeProvider; } public async Task RunWorkflowSync(string workflowId, int version, TData data, string reference, TimeSpan timeOut, bool persistSate = true) @@ -46,7 +48,7 @@ public async Task RunWorkflowSync(string workflowId, in Data = data, Description = def.Description, NextExecution = 0, - CreateTime = DateTime.Now.ToUniversalTime(), + CreateTime = _dateTimeProvider.UtcNow, Status = WorkflowStatus.Suspended, Reference = reference }; diff --git a/src/WorkflowCore/Services/WorkflowController.cs b/src/WorkflowCore/Services/WorkflowController.cs index 2a485c632..690a6a596 100755 --- a/src/WorkflowCore/Services/WorkflowController.cs +++ b/src/WorkflowCore/Services/WorkflowController.cs @@ -22,8 +22,9 @@ public class WorkflowController : IWorkflowController private readonly ILifeCycleEventHub _eventHub; private readonly IServiceProvider _serviceProvider; private readonly ILogger _logger; + private readonly IDateTimeProvider _dateTimeProvider; - public WorkflowController(IPersistenceProvider persistenceStore, IDistributedLockProvider lockProvider, IWorkflowRegistry registry, IQueueProvider queueProvider, IExecutionPointerFactory pointerFactory, ILifeCycleEventHub eventHub, ILoggerFactory loggerFactory, IServiceProvider serviceProvider) + public WorkflowController(IPersistenceProvider persistenceStore, IDistributedLockProvider lockProvider, IWorkflowRegistry registry, IQueueProvider queueProvider, IExecutionPointerFactory pointerFactory, ILifeCycleEventHub eventHub, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IDateTimeProvider dateTimeProvider) { _persistenceStore = persistenceStore; _lockProvider = lockProvider; @@ -33,6 +34,7 @@ public WorkflowController(IPersistenceProvider persistenceStore, IDistributedLoc _eventHub = eventHub; _serviceProvider = serviceProvider; _logger = loggerFactory.CreateLogger(); + _dateTimeProvider = dateTimeProvider; } public Task StartWorkflow(string workflowId, object data = null, string reference=null) @@ -68,7 +70,7 @@ public async Task StartWorkflow(string workflowId, int? version, Data = data, Description = def.Description, NextExecution = 0, - CreateTime = DateTime.Now.ToUniversalTime(), + CreateTime = _dateTimeProvider.UtcNow, Status = WorkflowStatus.Runnable, Reference = reference }; @@ -94,7 +96,7 @@ public async Task StartWorkflow(string workflowId, int? version, await _queueProvider.QueueWork(id, QueueType.Index); await _eventHub.PublishNotification(new WorkflowStarted() { - EventTimeUtc = DateTime.UtcNow, + EventTimeUtc = _dateTimeProvider.UtcNow, Reference = reference, WorkflowInstanceId = id, WorkflowDefinitionId = def.Id, @@ -111,7 +113,7 @@ public async Task PublishEvent(string eventName, string eventKey, object eventDa if (effectiveDate.HasValue) evt.EventTime = effectiveDate.Value.ToUniversalTime(); else - evt.EventTime = DateTime.Now.ToUniversalTime(); + evt.EventTime = _dateTimeProvider.UtcNow; evt.EventData = eventData; evt.EventKey = eventKey; @@ -137,7 +139,7 @@ public async Task SuspendWorkflow(string workflowId) await _queueProvider.QueueWork(workflowId, QueueType.Index); await _eventHub.PublishNotification(new WorkflowSuspended() { - EventTimeUtc = DateTime.UtcNow, + EventTimeUtc = _dateTimeProvider.UtcNow, Reference = wf.Reference, WorkflowInstanceId = wf.Id, WorkflowDefinitionId = wf.WorkflowDefinitionId, @@ -173,7 +175,7 @@ public async Task ResumeWorkflow(string workflowId) await _queueProvider.QueueWork(workflowId, QueueType.Index); await _eventHub.PublishNotification(new WorkflowResumed() { - EventTimeUtc = DateTime.UtcNow, + EventTimeUtc = _dateTimeProvider.UtcNow, Reference = wf.Reference, WorkflowInstanceId = wf.Id, WorkflowDefinitionId = wf.WorkflowDefinitionId, @@ -207,7 +209,7 @@ public async Task TerminateWorkflow(string workflowId) await _queueProvider.QueueWork(workflowId, QueueType.Index); await _eventHub.PublishNotification(new WorkflowTerminated() { - EventTimeUtc = DateTime.UtcNow, + EventTimeUtc = _dateTimeProvider.UtcNow, Reference = wf.Reference, WorkflowInstanceId = wf.Id, WorkflowDefinitionId = wf.WorkflowDefinitionId, diff --git a/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs index bb43a3397..57b6f6bc8 100644 --- a/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs @@ -21,7 +21,7 @@ public static WorkflowOptions UseAwsSimpleQueueService(this WorkflowOptions opti public static WorkflowOptions UseAwsDynamoLocking(this WorkflowOptions options, AWSCredentials credentials, AmazonDynamoDBConfig config, string tableName) { - options.UseDistributedLockManager(sp => new DynamoLockProvider(credentials, config, tableName, sp.GetService())); + options.UseDistributedLockManager(sp => new DynamoLockProvider(credentials, config, tableName, sp.GetService(), sp.GetService())); return options; } @@ -35,7 +35,7 @@ public static WorkflowOptions UseAwsDynamoPersistence(this WorkflowOptions optio public static WorkflowOptions UseAwsKinesis(this WorkflowOptions options, AWSCredentials credentials, RegionEndpoint region, string appName, string streamName) { options.Services.AddTransient(sp => new KinesisTracker(credentials, region, "workflowcore_kinesis", sp.GetService())); - options.Services.AddTransient(sp => new KinesisStreamConsumer(credentials, region, sp.GetService(), sp.GetService(), sp.GetService())); + options.Services.AddTransient(sp => new KinesisStreamConsumer(credentials, region, sp.GetService(), sp.GetService(), sp.GetService(), sp.GetService())); options.UseEventHub(sp => new KinesisProvider(credentials, region, appName, streamName, sp.GetService(), sp.GetService())); return options; } diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs index 2a7c2f7bd..b10dc4365 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs @@ -23,14 +23,16 @@ public class DynamoLockProvider : IDistributedLockProvider private Task _heartbeatTask; private CancellationTokenSource _cancellationTokenSource; private readonly AutoResetEvent _mutex = new AutoResetEvent(true); + private readonly IDateTimeProvider _dateTimeProvider; - public DynamoLockProvider(AWSCredentials credentials, AmazonDynamoDBConfig config, string tableName, ILoggerFactory logFactory) + public DynamoLockProvider(AWSCredentials credentials, AmazonDynamoDBConfig config, string tableName, ILoggerFactory logFactory, IDateTimeProvider dateTimeProvider) { _logger = logFactory.CreateLogger(); _client = new AmazonDynamoDBClient(credentials, config); _localLocks = new List(); _tableName = tableName; _nodeId = Guid.NewGuid().ToString(); + _dateTimeProvider = dateTimeProvider; } public async Task AcquireLock(string Id, CancellationToken cancellationToken) @@ -46,7 +48,7 @@ public async Task AcquireLock(string Id, CancellationToken cancellationTok { "lock_owner", new AttributeValue(_nodeId) }, { "expires", new AttributeValue() { - N = Convert.ToString(new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds() + _ttl) + N = Convert.ToString(new DateTimeOffset(_dateTimeProvider.UtcNow).ToUnixTimeMilliseconds() + _ttl) } } }, @@ -55,7 +57,7 @@ public async Task AcquireLock(string Id, CancellationToken cancellationTok { { ":expired", new AttributeValue() { - N = Convert.ToString(new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds() + _jitter) + N = Convert.ToString(new DateTimeOffset(_dateTimeProvider.UtcNow).ToUnixTimeMilliseconds() + _jitter) } } } @@ -154,7 +156,7 @@ private async void SendHeartbeat() { "lock_owner", new AttributeValue(_nodeId) }, { "expires", new AttributeValue() { - N = Convert.ToString(new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds() + _ttl) + N = Convert.ToString(new DateTimeOffset(_dateTimeProvider.UtcNow).ToUnixTimeMilliseconds() + _ttl) } } }, diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisStreamConsumer.cs b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisStreamConsumer.cs index c22e40fce..2a3a42494 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisStreamConsumer.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisStreamConsumer.cs @@ -23,8 +23,9 @@ public class KinesisStreamConsumer : IKinesisStreamConsumer, IDisposable private readonly Task _processTask; private readonly int _batchSize = 100; private ICollection _subscribers = new HashSet(); + private readonly IDateTimeProvider _dateTimeProvider; - public KinesisStreamConsumer(AWSCredentials credentials, RegionEndpoint region, IKinesisTracker tracker, IDistributedLockProvider lockManager, ILoggerFactory logFactory) + public KinesisStreamConsumer(AWSCredentials credentials, RegionEndpoint region, IKinesisTracker tracker, IDistributedLockProvider lockManager, ILoggerFactory logFactory, IDateTimeProvider dateTimeProvider) { _logger = logFactory.CreateLogger(GetType()); _tracker = tracker; @@ -32,6 +33,7 @@ public KinesisStreamConsumer(AWSCredentials credentials, RegionEndpoint region, _client = new AmazonKinesisClient(credentials, region); _processTask = new Task(Process); _processTask.Start(); + _dateTimeProvider = dateTimeProvider; } public async Task Subscribe(string appName, string stream, Action action) @@ -59,7 +61,7 @@ private async void Process() { try { - var todo = _subscribers.Where(x => x.Snooze < DateTime.Now).ToList(); + var todo = _subscribers.Where(x => x.Snooze < _dateTimeProvider.Now).ToList(); foreach (var sub in todo) { if (!await _lockManager.AcquireLock($"{sub.AppName}.{sub.Stream}.{sub.Shard.ShardId}", @@ -71,7 +73,7 @@ private async void Process() var records = await GetBatch(sub); if (records.Records.Count == 0) - sub.Snooze = DateTime.Now.AddSeconds(5); + sub.Snooze = _dateTimeProvider.Now.AddSeconds(5); var lastSequence = string.Empty; diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs index 79a15b970..103e7c442 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs @@ -62,7 +62,7 @@ public async Task PersistWorkflow(WorkflowInstance workflow) public async Task> GetRunnableInstances(DateTime asAt) { var result = new List(); - var data = await _redis.SortedSetRangeByScoreAsync($"{_prefix}.{WORKFLOW_SET}.{RUNNABLE_INDEX}", -1, DateTime.UtcNow.Ticks); + var data = await _redis.SortedSetRangeByScoreAsync($"{_prefix}.{WORKFLOW_SET}.{RUNNABLE_INDEX}", -1, asAt.ToUniversalTime().Ticks); foreach (var item in data) result.Add(item); From e609f7f0aba88068fa81ced7cf7924ee0a4e7f50 Mon Sep 17 00:00:00 2001 From: glucaci Date: Sun, 13 Dec 2020 13:32:12 +0100 Subject: [PATCH 052/342] Naming --- src/WorkflowCore/Models/WorkflowOptions.cs | 8 ++++---- src/WorkflowCore/ServiceCollectionExtensions.cs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/WorkflowCore/Models/WorkflowOptions.cs b/src/WorkflowCore/Models/WorkflowOptions.cs index f6e370283..bf2d28e06 100644 --- a/src/WorkflowCore/Models/WorkflowOptions.cs +++ b/src/WorkflowCore/Models/WorkflowOptions.cs @@ -34,10 +34,10 @@ public WorkflowOptions(IServiceCollection services) EventHubFactory = new Func(sp => new SingleNodeEventHub(sp.GetService())); } - public bool DisableWorkflowConsumer { get; set; } = false; - public bool DisableEventConsumer { get; set; } = false; - public bool DisableIndexConsumer { get; set; } = false; - public bool DisableRunnablePoller { get; set; } = false; + public bool EnableWorkflows { get; set; } = true; + public bool EnableEvents { get; set; } = true; + public bool EnableIndexes { get; set; } = true; + public bool EnablePolling { get; set; } = true; public void UsePersistence(Func factory) { diff --git a/src/WorkflowCore/ServiceCollectionExtensions.cs b/src/WorkflowCore/ServiceCollectionExtensions.cs index d56b4484b..feb10c726 100644 --- a/src/WorkflowCore/ServiceCollectionExtensions.cs +++ b/src/WorkflowCore/ServiceCollectionExtensions.cs @@ -37,22 +37,22 @@ public static IServiceCollection AddWorkflow(this IServiceCollection services, A services.AddSingleton(options); services.AddSingleton(); - if (!options.DisableWorkflowConsumer) + if (!options.EnableWorkflows) { services.AddTransient(); } - if (!options.DisableEventConsumer) + if (!options.EnableEvents) { services.AddTransient(); } - if (!options.DisableIndexConsumer) + if (!options.EnableIndexes) { services.AddTransient(); } - if (!options.DisableRunnablePoller) + if (!options.EnablePolling) { services.AddTransient(); } From 8bcd41c7608a1b7134c0a37bf49143842b9a5907 Mon Sep 17 00:00:00 2001 From: glucaci Date: Mon, 14 Dec 2020 17:07:59 +0100 Subject: [PATCH 053/342] Reverse registration logic --- src/WorkflowCore/ServiceCollectionExtensions.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WorkflowCore/ServiceCollectionExtensions.cs b/src/WorkflowCore/ServiceCollectionExtensions.cs index feb10c726..0e4f17f8f 100644 --- a/src/WorkflowCore/ServiceCollectionExtensions.cs +++ b/src/WorkflowCore/ServiceCollectionExtensions.cs @@ -37,22 +37,22 @@ public static IServiceCollection AddWorkflow(this IServiceCollection services, A services.AddSingleton(options); services.AddSingleton(); - if (!options.EnableWorkflows) + if (options.EnableWorkflows) { services.AddTransient(); } - if (!options.EnableEvents) + if (options.EnableEvents) { services.AddTransient(); } - if (!options.EnableIndexes) + if (options.EnableIndexes) { services.AddTransient(); } - if (!options.EnablePolling) + if (options.EnablePolling) { services.AddTransient(); } From 19f90efafa6da0a382901d2da790c7c09413835f Mon Sep 17 00:00:00 2001 From: Stephen Brown Date: Tue, 15 Dec 2020 13:28:08 +0100 Subject: [PATCH 054/342] Upgrade to .net 5.0 and EF Core 5.0 --- src/WorkflowCore/WorkflowCore.csproj | 8 ++++---- ...rkflowCore.Persistence.EntityFramework.csproj | 14 +++++++------- .../WorkflowCore.Persistence.MySQL.csproj | 12 ++++++------ .../WorkflowCore.Persistence.PostgreSQL.csproj | 16 ++++++++-------- .../SqlServerContext.cs | 12 ++++++------ .../WorkflowCore.Persistence.SqlServer.csproj | 16 ++++++++-------- .../WorkflowCore.Persistence.Sqlite.csproj | 12 ++++++------ .../WorkflowCore.QueueProviders.SqlServer.csproj | 4 ++-- .../WorkflowCore.Sample01.csproj | 14 +++++++------- .../WorkflowCore.Sample02.csproj | 6 +++--- .../WorkflowCore.Sample03.csproj | 8 ++++---- .../WorkflowCore.Sample04.csproj | 8 ++++---- .../WorkflowCore.Sample05.csproj | 2 +- .../WorkflowCore.Sample06.csproj | 2 +- .../WorkflowCore.Sample07.csproj | 4 ++-- .../WorkflowCore.Sample08.csproj | 4 ++-- .../WorkflowCore.Sample09.csproj | 4 ++-- .../WorkflowCore.Sample09s.csproj | 6 +++--- .../WorkflowCore.Sample10.csproj | 4 ++-- .../WorkflowCore.Sample11.csproj | 6 +++--- .../WorkflowCore.Sample12.csproj | 4 ++-- .../WorkflowCore.Sample13.csproj | 4 ++-- .../WorkflowCore.Sample14.csproj | 2 +- .../WorkflowCore.Sample15.csproj | 6 +++--- .../WorkflowCore.Sample16.csproj | 6 +++--- .../WorkflowCore.Sample17.csproj | 4 ++-- .../WorkflowCore.Sample18.csproj | 12 ++++++------ .../WorkflowCore.Sample19.csproj | 12 ++++++------ .../WorkflowCore.TestSample01.csproj | 4 ++-- test/ScratchPad/ScratchPad.csproj | 6 +++--- .../WorkflowCore.IntegrationTests.csproj | 8 ++++---- .../WorkflowCore.TestAssets.csproj | 2 +- .../WorkflowCore.Testing.csproj | 12 ++++++------ .../WorkflowCore.Tests.DynamoDB.csproj | 2 +- .../WorkflowCore.Tests.Elasticsearch.csproj | 2 +- .../WorkflowCore.Tests.MongoDB.csproj | 8 ++++---- .../WorkflowCore.Tests.MySQL.csproj | 4 ++-- .../WorkflowCore.Tests.PostgreSQL.csproj | 4 ++-- .../WorkflowCore.Tests.Redis.csproj | 4 ++-- .../WorkflowCore.Tests.SqlServer.csproj | 2 +- .../WorkflowCore.Tests.Sqlite.csproj | 2 +- .../WorkflowCore.UnitTests.csproj | 8 ++++---- 42 files changed, 140 insertions(+), 140 deletions(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 53cd19bcd..36e9f45c1 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.3.2 - 3.3.2.0 - 3.3.2.0 + 3.3.3 + 3.3.3.0 + 3.3.3.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.3.2 + 3.3.3 diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index ed8392a62..214787365 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -3,7 +3,7 @@ Workflow Core EntityFramework Core Persistence Provider Daniel Gerlag - netstandard2.0 + netstandard2.1 WorkflowCore.Persistence.EntityFramework WorkflowCore.Persistence.EntityFramework workflow;.NET;Core;state machine;WorkflowCore;EntityFramework;EntityFrameworkCore @@ -14,11 +14,11 @@ false false false - 3.1.0 + 3.3.3 Base package for Workflow-core peristence providers using entity framework - 3.1.0.0 - 3.1.0.0 - 3.1.0 + 3.3.3.0 + 3.3.3.0 + 3.3.3 @@ -26,8 +26,8 @@ - - + + diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index a031e5fba..f1b09d045 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -4,7 +4,7 @@ Workflow Core MySQL Persistence Provider 1.0.0 Daniel Gerlag - netstandard2.0 + netstandard2.1 WorkflowCore.Persistence.MySQL WorkflowCore.Persistence.MySQL workflow;.NET;Core;state machine;WorkflowCore;MySQL @@ -16,17 +16,17 @@ false false Provides support to persist workflows running on Workflow Core to a MySQL database. - 3.0.1 - 3.0.1.0 - 3.0.1.0 + 3.3.3 + 3.3.3.0 + 3.3.3.0 - + all runtime; build; native; contentfiles; analyzers - + diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index 7addc52a4..a041d19b1 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -15,10 +15,10 @@ false false Provides support to persist workflows running on Workflow Core to a PostgreSQL database. - 3.1.0 - 3.1.0.0 - 3.1.0.0 - 3.1.0 + 3.3.3 + 3.3.3.0 + 3.3.3.0 + 3.3.3 @@ -27,12 +27,12 @@ - - - + + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs b/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs index 499c10295..7383cce3e 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs @@ -28,37 +28,37 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) protected override void ConfigureSubscriptionStorage(EntityTypeBuilder builder) { builder.ToTable("Subscription", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureWorkflowStorage(EntityTypeBuilder builder) { builder.ToTable("Workflow", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureExecutionPointerStorage(EntityTypeBuilder builder) { builder.ToTable("ExecutionPointer", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureExecutionErrorStorage(EntityTypeBuilder builder) { builder.ToTable("ExecutionError", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureExetensionAttributeStorage(EntityTypeBuilder builder) { builder.ToTable("ExtensionAttribute", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureEventStorage(EntityTypeBuilder builder) { builder.ToTable("Event", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } } } diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index be52279d1..427bbbdf3 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -4,7 +4,7 @@ Workflow Core SQL Server Persistence Provider 1.8.0 Daniel Gerlag - netstandard2.0 + netstandard2.1 WorkflowCore.Persistence.SqlServer WorkflowCore.Persistence.SqlServer workflow;.NET;Core;state machine;WorkflowCore @@ -15,11 +15,11 @@ false false false - 3.1.0 + 3.3.3 Provides support to persist workflows running on Workflow Core to a SQL Server database. - 3.1.0.0 - 3.1.0.0 - 3.1.0 + 3.3.3.0 + 3.3.3.0 + 3.3.3 @@ -28,11 +28,11 @@ - - + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj index 2d2789021..ddcc8deac 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj +++ b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj @@ -4,7 +4,7 @@ Workflow Core Sqlite Persistence Provider 1.5.0 Daniel Gerlag - netstandard2.0 + netstandard2.1 WorkflowCore.Persistence.Sqlite WorkflowCore.Persistence.Sqlite workflow;.NET;Core;state machine;WorkflowCore;Sqlite @@ -16,10 +16,10 @@ false false Provides support to persist workflows running on Workflow Core to a Sqlite database. - 3.1.0 - 3.1.0.0 - 3.1.0.0 - 3.1.0 + 3.3.3 + 3.3.3.0 + 3.3.3.0 + 3.3.3 @@ -28,7 +28,7 @@ - + diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj index 36d7cda77..97b48d220 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj @@ -5,7 +5,7 @@ Roberto Paterlini Queue provider for Workflow-core using SQL Server Service Broker - 1.0.3-alpha + 1.0.4-alpha @@ -20,7 +20,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj b/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj index e4a09e491..5f4857cca 100644 --- a/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj +++ b/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 WorkflowCore.Sample01 Exe WorkflowCore.Sample01 @@ -16,12 +16,12 @@ - - - - - - + + + + + + diff --git a/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj b/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj index 0765d50c3..7fab128b6 100644 --- a/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj +++ b/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 WorkflowCore.Sample02 Exe WorkflowCore.Sample02 @@ -11,8 +11,8 @@ - - + + diff --git a/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj b/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj index fc4a5d4fd..7b332dcd9 100644 --- a/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj +++ b/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp3.1 WorkflowCore.Sample03 Exe WorkflowCore.Sample03 @@ -16,9 +16,9 @@ - - - + + + diff --git a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj index 82107b0e6..af4dd01f9 100644 --- a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj +++ b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 WorkflowCore.Sample04 Exe WorkflowCore.Sample04 @@ -29,9 +29,9 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + diff --git a/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj b/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj index 592fa228b..069931ef0 100644 --- a/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj +++ b/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj b/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj index b61478b9e..d4c71d9aa 100644 --- a/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj +++ b/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj index 5ca51a866..2f5937f36 100644 --- a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj +++ b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 true WorkflowCore.Sample07 Exe @@ -26,7 +26,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj b/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj index 3ff429e28..2a556e45d 100644 --- a/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj +++ b/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 WorkflowCore.Sample08 Exe WorkflowCore.Sample08 @@ -21,7 +21,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj b/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj index 6f75a0d7d..bc16eb974 100644 --- a/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj +++ b/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.0 + netcoreapp3.1 - + diff --git a/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj b/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj index e569ec895..bc16eb974 100644 --- a/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj +++ b/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj @@ -1,12 +1,12 @@ - + Exe - netcoreapp3.0 + netcoreapp3.1 - + diff --git a/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj b/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj index 6f75a0d7d..bc16eb974 100644 --- a/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj +++ b/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.0 + netcoreapp3.1 - + diff --git a/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj b/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj index b6454f6a2..4eb65c992 100644 --- a/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj +++ b/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj @@ -2,12 +2,12 @@ Exe - netcoreapp2.2 + netcoreapp3.1 - - + + diff --git a/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj b/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj index 9879baab2..5b030fb75 100644 --- a/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj +++ b/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.0 + netcoreapp3.1 - + diff --git a/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj b/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj index dbe49166e..7f814f488 100644 --- a/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj +++ b/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp2.2 + netcoreapp3.1 - + diff --git a/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj b/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj index fef8173cc..974472a25 100644 --- a/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj +++ b/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.2 + netcoreapp3.1 diff --git a/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj b/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj index c63fbd792..9fd7656d7 100644 --- a/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj +++ b/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj @@ -2,12 +2,12 @@ Exe - netcoreapp2.2 + netcoreapp3.1 - - + + diff --git a/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj b/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj index c63fbd792..9fd7656d7 100644 --- a/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj +++ b/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj @@ -2,12 +2,12 @@ Exe - netcoreapp2.2 + netcoreapp3.1 - - + + diff --git a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj index 26933096d..0c1689366 100644 --- a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj +++ b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.0 + netcoreapp3.1 - + diff --git a/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj b/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj index 660b47511..46ad70bf5 100644 --- a/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj +++ b/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj @@ -1,15 +1,15 @@ - + Exe - netcoreapp3.0 + netcoreapp3.1 - - - - + + + + diff --git a/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj b/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj index b2a7796c3..f1fbd9c5c 100644 --- a/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj +++ b/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj @@ -1,15 +1,15 @@ - + Exe - netcoreapp3.0 + netcoreapp3.1 - - - - + + + + diff --git a/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj b/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj index 282fdbb15..789e6e445 100644 --- a/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj +++ b/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj @@ -1,12 +1,12 @@  - netcoreapp2.2 + netcoreapp3.1 - + diff --git a/test/ScratchPad/ScratchPad.csproj b/test/ScratchPad/ScratchPad.csproj index 4fb61dd24..27c262350 100644 --- a/test/ScratchPad/ScratchPad.csproj +++ b/test/ScratchPad/ScratchPad.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 ScratchPad Exe ScratchPad @@ -11,8 +11,8 @@ - - + + diff --git a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj index 971f10c57..8739a6c6d 100644 --- a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj +++ b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 WorkflowCore.IntegrationTests WorkflowCore.IntegrationTests true @@ -21,10 +21,10 @@ - - + + - + diff --git a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj index 12da1f57b..aeeb3d614 100644 --- a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj +++ b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 WorkflowCore.TestAssets WorkflowCore.TestAssets false diff --git a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj index 32f9c1363..981d713c4 100644 --- a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj +++ b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj @@ -2,16 +2,16 @@ netstandard2.0 - 2.3.0 - 2.3.0.0 - 2.3.0.0 + 2.3.1 + 2.3.1.0 + 2.3.1.0 Facilitates testing of workflows built on Workflow-Core - - - + + + diff --git a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj index c2563b8b2..f275a05cf 100644 --- a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj +++ b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.1 false diff --git a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj index 168be514f..0ed01e311 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj +++ b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 false diff --git a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj index bec4d8561..cb4beac90 100644 --- a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj +++ b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 WorkflowCore.Tests.MongoDB WorkflowCore.Tests.MongoDB true @@ -22,9 +22,9 @@ - - - + + + diff --git a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj index a255e01d6..66a792fe5 100644 --- a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj +++ b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj @@ -1,7 +1,7 @@ - + - netcoreapp2.2 + netcoreapp3.1 false diff --git a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj index 1cc7d56bd..2fefbdea8 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj +++ b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 WorkflowCore.Tests.PostgreSQL WorkflowCore.Tests.PostgreSQL true @@ -21,7 +21,7 @@ - + diff --git a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj index c5ee9a6f8..76857bc6d 100644 --- a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj +++ b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj @@ -1,7 +1,7 @@ - + - netcoreapp2.2 + netcoreapp3.1 false diff --git a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj index 011714983..497293aaf 100644 --- a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj +++ b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 diff --git a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj index 9ce1b77cd..9598398f4 100644 --- a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj +++ b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 diff --git a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj index 294adbd23..bc8321631 100644 --- a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj +++ b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 WorkflowCore.UnitTests WorkflowCore.UnitTests true @@ -20,9 +20,9 @@ - - - + + + From 0e2d0fa03e119e977d1981f6da069a75a41bde9a Mon Sep 17 00:00:00 2001 From: Stephen Brown Date: Tue, 15 Dec 2020 13:34:28 +0100 Subject: [PATCH 055/342] Upgrade to EF Core 5.0.1 --- .../WorkflowCore.Persistence.EntityFramework.csproj | 4 ++-- .../WorkflowCore.Persistence.MySQL.csproj | 2 +- .../WorkflowCore.Persistence.PostgreSQL.csproj | 4 ++-- .../WorkflowCore.Persistence.SqlServer.csproj | 6 +++--- .../WorkflowCore.Persistence.Sqlite.csproj | 2 +- .../WorkflowCore.Sample01/WorkflowCore.Sample01.csproj | 2 +- .../WorkflowCore.Sample04/WorkflowCore.Sample04.csproj | 2 +- .../WorkflowCore.Sample11/WorkflowCore.Sample11.csproj | 2 +- .../WorkflowCore.Sample15/WorkflowCore.Sample15.csproj | 2 +- .../WorkflowCore.Sample16/WorkflowCore.Sample16.csproj | 2 +- .../WorkflowCore.Sample17/WorkflowCore.Sample17.csproj | 2 +- .../WorkflowCore.Sample18/WorkflowCore.Sample18.csproj | 2 +- .../WorkflowCore.Sample19/WorkflowCore.Sample19.csproj | 2 +- .../WorkflowCore.TestSample01.csproj | 2 +- test/ScratchPad/ScratchPad.csproj | 2 +- .../WorkflowCore.IntegrationTests.csproj | 2 +- test/WorkflowCore.Testing/WorkflowCore.Testing.csproj | 2 +- .../WorkflowCore.Tests.MongoDB.csproj | 2 +- test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj | 2 +- 19 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index 214787365..a08f951d9 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -26,8 +26,8 @@ - - + + diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index f1b09d045..f40289070 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -22,7 +22,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index a041d19b1..a5faadf44 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -29,10 +29,10 @@ - + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index 427bbbdf3..835f26433 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -28,11 +28,11 @@ - - + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj index ddcc8deac..44e1e344e 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj +++ b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj @@ -28,7 +28,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj b/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj index 5f4857cca..0e878eb0b 100644 --- a/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj +++ b/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj index af4dd01f9..af988640d 100644 --- a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj +++ b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj @@ -25,7 +25,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj b/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj index 4eb65c992..5a8923eeb 100644 --- a/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj +++ b/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj b/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj index 9fd7656d7..79ed2ba57 100644 --- a/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj +++ b/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj b/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj index 9fd7656d7..79ed2ba57 100644 --- a/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj +++ b/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj index 0c1689366..766fc8e0c 100644 --- a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj +++ b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj b/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj index 46ad70bf5..5f9b64824 100644 --- a/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj +++ b/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj b/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj index f1fbd9c5c..0f169bcc8 100644 --- a/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj +++ b/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj b/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj index 789e6e445..71454dc11 100644 --- a/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj +++ b/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj @@ -6,7 +6,7 @@ - + diff --git a/test/ScratchPad/ScratchPad.csproj b/test/ScratchPad/ScratchPad.csproj index 27c262350..4da4684ed 100644 --- a/test/ScratchPad/ScratchPad.csproj +++ b/test/ScratchPad/ScratchPad.csproj @@ -11,7 +11,7 @@ - + diff --git a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj index 8739a6c6d..f7634e8a9 100644 --- a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj +++ b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj @@ -21,7 +21,7 @@ - + diff --git a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj index 981d713c4..22b68fb2f 100644 --- a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj +++ b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj @@ -9,7 +9,7 @@ - + diff --git a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj index cb4beac90..1523f31ea 100644 --- a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj +++ b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj @@ -22,7 +22,7 @@ - + diff --git a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj index bc8321631..5ec1e2ff1 100644 --- a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj +++ b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj @@ -20,7 +20,7 @@ - + From dee17c27e0b18ed22293756b38bb1502546b4fb9 Mon Sep 17 00:00:00 2001 From: "xavid.ramirez@apchomehealth.onmicrosoft.com" Date: Wed, 16 Dec 2020 14:12:32 -0600 Subject: [PATCH 056/342] Adding RavenDB persistence provider --- WorkflowCore.sln | 7 + .../RavenStoreOptions.cs | 14 + .../ServiceCollectionExtensions.cs | 39 +++ .../Services/RavenDbIndexes.cs | 14 + .../Services/RavendbPersistenceProvider.cs | 320 ++++++++++++++++++ .../Services/WorkflowPurger.cs | 42 +++ .../WorkflowCore.Persistence.RavenDB.csproj | 32 ++ 7 files changed, 468 insertions(+) create mode 100644 src/providers/WorkflowCore.Persistence.RavenDB/RavenStoreOptions.cs create mode 100644 src/providers/WorkflowCore.Persistence.RavenDB/ServiceCollectionExtensions.cs create mode 100644 src/providers/WorkflowCore.Persistence.RavenDB/Services/RavenDbIndexes.cs create mode 100644 src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs create mode 100644 src/providers/WorkflowCore.Persistence.RavenDB/Services/WorkflowPurger.cs create mode 100644 src/providers/WorkflowCore.Persistence.RavenDB/WorkflowCore.Persistence.RavenDB.csproj diff --git a/WorkflowCore.sln b/WorkflowCore.sln index 1ef2a187f..be18fd721 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -150,6 +150,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Tests.QueuePro EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample19", "src\samples\WorkflowCore.Sample19\WorkflowCore.Sample19.csproj", "{1223ED47-3E5E-4960-B70D-DFAF550F6666}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Persistence.RavenDB", "src\providers\WorkflowCore.Persistence.RavenDB\WorkflowCore.Persistence.RavenDB.csproj", "{AF205715-C8B7-42EF-BF14-AFC9E7F27242}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -368,6 +370,10 @@ Global {1223ED47-3E5E-4960-B70D-DFAF550F6666}.Debug|Any CPU.Build.0 = Debug|Any CPU {1223ED47-3E5E-4960-B70D-DFAF550F6666}.Release|Any CPU.ActiveCfg = Release|Any CPU {1223ED47-3E5E-4960-B70D-DFAF550F6666}.Release|Any CPU.Build.0 = Release|Any CPU + {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -429,6 +435,7 @@ Global {51BB7DCD-01DD-453D-A1E7-17E5E3DBB14C} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} {54DE20BA-EBA7-4BF0-9BD9-F03766849716} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} {1223ED47-3E5E-4960-B70D-DFAF550F6666} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} + {AF205715-C8B7-42EF-BF14-AFC9E7F27242} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC0FA8D3-6449-4FDA-BB46-ECF58FAD23B4} diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/RavenStoreOptions.cs b/src/providers/WorkflowCore.Persistence.RavenDB/RavenStoreOptions.cs new file mode 100644 index 000000000..00a420668 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.RavenDB/RavenStoreOptions.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace WorkflowCore.Persistence.RavenDB +{ + public class RavenStoreOptions + { + public string ServerUrl { get; set; } + public string DatabaseName { get; set; } + public string CertificatePath { get; set; } + public string CertificatePassword { get; set; } + } +} diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Persistence.RavenDB/ServiceCollectionExtensions.cs new file mode 100644 index 000000000..4b7d12926 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.RavenDB/ServiceCollectionExtensions.cs @@ -0,0 +1,39 @@ +using Raven.Client.Documents.Operations; +using System; +using System.Collections.Generic; +using System.Text; +using WorkflowCore.Models; +using Raven.Client; +using Raven.Client.Documents; +using System.Security.Cryptography.X509Certificates; +using WorkflowCore.Persistence.RavenDB.Services; +using WorkflowCore.Interface; +using WorkflowCore.Persistence.RavenDB; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class ServiceCollectionExtensions + { + public static WorkflowOptions UseRavenDB(this WorkflowOptions options, RavenStoreOptions configOptions) + { + IDocumentStore store = new DocumentStore + { + Urls = new[] { configOptions.ServerUrl }, + Database = configOptions.DatabaseName, + Certificate = new X509Certificate2(configOptions.CertificatePath, configOptions.CertificatePassword) + }.Initialize(); + + options.UsePersistence(sp => + { + return new RavendbPersistenceProvider(store); + }); + + options.Services.AddTransient(sp => + { + return new WorkflowPurger(store); + }); + + return options; + } + } +} \ No newline at end of file diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavenDbIndexes.cs b/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavenDbIndexes.cs new file mode 100644 index 000000000..75f5ab106 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavenDbIndexes.cs @@ -0,0 +1,14 @@ +using Raven.Client.Documents.Indexes; +using System; +using System.Collections.Generic; +using System.Text; +using WorkflowCore.Models; + +namespace WorkflowCore.Persistence.RavenDB.Services +{ + // TODO: Implement Map for result bind of Index + public class WorkflowInstances_Id : AbstractIndexCreationTask { } + public class EventSubscriptions_Id : AbstractIndexCreationTask { } + public class Events_Id : AbstractIndexCreationTask { } + public class ExecutionErrors_Id : AbstractIndexCreationTask { } +} diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs new file mode 100644 index 000000000..66d38b5aa --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs @@ -0,0 +1,320 @@ +using Raven.Client.Documents; +using Raven.Client.Documents.Indexes; +using Raven.Client.Documents.Linq; +using Raven.Client.Documents.Operations; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Persistence.RavenDB.Services +{ + public class RavendbPersistenceProvider : IPersistenceProvider + { + internal const string WorkflowCollectionName = "wfc.workflows"; + private readonly IDocumentStore _database; + static bool indexesCreated = false; + + public RavendbPersistenceProvider(IDocumentStore database) + { + _database = database; + CreateIndexes(this); + } + + static void CreateIndexes(RavendbPersistenceProvider instance) + { + if (!indexesCreated) + { + /* + // create the indexes here based on assemby of classes in the file 'RavenDbIndexes.cs' + IndexCreation.CreateIndexes(typeof(WorkflowInstances_Id).Assembly, instance._database); + IndexCreation.CreateIndexes(typeof(EventSubscriptions_Id).Assembly, instance._database); + IndexCreation.CreateIndexes(typeof(Events_Id).Assembly, instance._database); + IndexCreation.CreateIndexes(typeof(ExecutionErrors_Id).Assembly, instance._database); + */ + indexesCreated = true; + } + } + + public async Task CreateNewWorkflow(WorkflowInstance workflow) + { + using (var session = _database.OpenAsyncSession()) + { + await session.StoreAsync(workflow); + var id = workflow.Id; + await session.SaveChangesAsync(); + return id; + } + } + + public async Task PersistWorkflow(WorkflowInstance workflow) + { + using (var session = _database.OpenAsyncSession()) + { + session.Advanced.Patch(workflow.Id, x => x.WorkflowDefinitionId, workflow.WorkflowDefinitionId); + session.Advanced.Patch(workflow.Id, x => x.Version, workflow.Version); + session.Advanced.Patch(workflow.Id, x => x.Description, workflow.Description); + session.Advanced.Patch(workflow.Id, x => x.Reference, workflow.Reference); + session.Advanced.Patch(workflow.Id, x => x.ExecutionPointers, workflow.ExecutionPointers); + session.Advanced.Patch(workflow.Id, x => x.NextExecution, workflow.NextExecution); + session.Advanced.Patch(workflow.Id, x => x.Status, workflow.Status); + session.Advanced.Patch(workflow.Id, x => x.Data, workflow.Data); + session.Advanced.Patch(workflow.Id, x => x.CreateTime, workflow.CreateTime); + session.Advanced.Patch(workflow.Id, x => x.CompleteTime, workflow.CompleteTime); + + await session.SaveChangesAsync(); + } + } + + public async Task> GetRunnableInstances(DateTime asAt) + { + var now = asAt.ToUniversalTime().Ticks; + using (var session = _database.OpenAsyncSession()) + { + var l = session.Query().Where(w => w.NextExecution.HasValue + && (w.NextExecution <= now) + && (w.Status == WorkflowStatus.Runnable) + ).Select(x => x.Id); + + return await l.ToListAsync(); + } + } + + public async Task GetWorkflowInstance(string Id) + { + using (var session = _database.OpenAsyncSession()) + { + var result = await session.Query().FirstOrDefaultAsync(x => x.Id == Id); + return result; + } + } + + public async Task> GetWorkflowInstances(IEnumerable ids) + { + if (ids == null) + { + return new List(); + } + + using (var session = _database.OpenAsyncSession()) + { + var list = session.Query().Where(x => x.Id.In(ids)); + return await list.ToListAsync(); + } + } + + public async Task> GetWorkflowInstances(WorkflowStatus? status, string type, DateTime? createdFrom, DateTime? createdTo, int skip, int take) + { + using (var session = _database.OpenAsyncSession()) + { + var result = session.Query(); + + if (status.HasValue) + result = result.Where(x => x.Status == status.Value); + + if (!String.IsNullOrEmpty(type)) + result = result.Where(x => x.WorkflowDefinitionId == type); + + if (createdFrom.HasValue) + result = result.Where(x => x.CreateTime >= createdFrom.Value); + + if (createdTo.HasValue) + result = result.Where(x => x.CreateTime <= createdTo.Value); + + return await result.Skip(skip).Take(take).ToListAsync(); + } + } + + public async Task CreateEventSubscription(EventSubscription subscription) + { + using (var session = _database.OpenAsyncSession()) + { + await session.StoreAsync(subscription); + var id = subscription.Id; + await session.SaveChangesAsync(); + return id; + } + } + + public async Task TerminateSubscription(string eventSubscriptionId) + { + using (var session = _database.OpenAsyncSession()) + { + session.Delete(eventSubscriptionId); + await Task.CompletedTask; + } + } + + public async Task GetSubscription(string eventSubscriptionId) + { + using (var session = _database.OpenAsyncSession()) + { + var result = session.Query().Where(x => x.Id == eventSubscriptionId); + return await result.FirstOrDefaultAsync(); + } + } + + public async Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf) + { + using (var session = _database.OpenAsyncSession()) + { + var q = session.Query().Where(x => + x.EventName == eventKey + && x.EventKey == eventKey + && x.SubscribeAsOf <= asOf + && x.ExternalToken == null + ); + + return await q.FirstOrDefaultAsync(); + } + } + + public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry) + { + try + { + // The query string + var strbuilder = new StringBuilder(); + strbuilder.Append("from EventSubscriptions as e "); + strbuilder.Append($"where e.Id = {eventSubscriptionId} and ExternalToken = null"); + strbuilder.Append("update"); + strbuilder.Append("{"); + strbuilder.Append($"e.ExternalToken = '{token}'"); + strbuilder.Append($"e.ExternalTokenExpiry = '{expiry}'"); + strbuilder.Append($"e.ExternalWorkerId = 'workerId'"); + strbuilder.Append("}"); + + var operation = await _database.Operations.SendAsync(new PatchByQueryOperation(strbuilder.ToString())); + operation.WaitForCompletion(); + return true; + } + catch (Exception e) + { + return false; + } + } + + public async Task ClearSubscriptionToken(string eventSubscriptionId, string token) + { + try + { + // The query string + var strbuilder = new StringBuilder(); + strbuilder.Append("from EventSubscriptions as e "); + strbuilder.Append($"where e.Id = {eventSubscriptionId} and ExternalToken = '{token}'"); + strbuilder.Append("update"); + strbuilder.Append("{"); + strbuilder.Append($"e.ExternalToken = null"); + strbuilder.Append($"e.ExternalTokenExpiry = null"); + strbuilder.Append($"e.ExternalWorkerId = null"); + strbuilder.Append("}"); + + var operation = await _database.Operations.SendAsync(new PatchByQueryOperation(strbuilder.ToString())); + operation.WaitForCompletion(); + } + catch (Exception e) + { + throw e; + } + } + + public void EnsureStoreExists() { } + + public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf) + { + using (var session = _database.OpenAsyncSession()) + { + var q = session.Query().Where(x => + x.EventName == eventName + && x.EventKey == eventKey + && x.SubscribeAsOf <= asOf + ); + + return await q.ToListAsync(); + } + } + + public async Task CreateEvent(Event newEvent) + { + using (var session = _database.OpenAsyncSession()) + { + await session.StoreAsync(newEvent); + var id = newEvent.Id; + await session.SaveChangesAsync(); + return id; + } + } + + public async Task GetEvent(string id) + { + using (var session = _database.OpenAsyncSession()) + { + var result = session.Query().Where(x => x.Id == id); + return await result.FirstAsync(); + } + } + + public async Task> GetRunnableEvents(DateTime asAt) + { + using (var session = _database.OpenAsyncSession()) + { + var now = asAt.ToUniversalTime(); + var result = session.Query() + .Where(x => !x.IsProcessed && x.EventTime < now) + .Select(x => x.Id); + + return await result.ToListAsync(); + } + } + + public async Task MarkEventProcessed(string id) + { + using (var session = _database.OpenAsyncSession()) + { + session.Advanced.Patch(id, x => x.IsProcessed, true); + + await session.SaveChangesAsync(); + } + } + + public async Task> GetEvents(string eventName, string eventKey, DateTime asOf) + { + using (var session = _database.OpenAsyncSession()) + { + var q = session.Query() + .Where(x => + x.EventName == eventName + && x.EventKey == eventKey + && x.EventTime >= asOf) + .Select(x => x.Id); + + return await q.ToListAsync(); + } + } + + public async Task MarkEventUnprocessed(string id) + { + using (var session = _database.OpenAsyncSession()) + { + session.Advanced.Patch(id, x => x.IsProcessed, false); + + await session.SaveChangesAsync(); + } + } + + public async Task PersistErrors(IEnumerable errors) + { + if (errors.Any()) + { + var blk = _database.BulkInsert(); + foreach (var error in errors) + await blk.StoreAsync(error); + + } + } + + } +} diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/Services/WorkflowPurger.cs b/src/providers/WorkflowCore.Persistence.RavenDB/Services/WorkflowPurger.cs new file mode 100644 index 000000000..70fd0210b --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.RavenDB/Services/WorkflowPurger.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Text; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using Raven.Client; +using System.Threading.Tasks; +using Raven.Client.Documents; +using System.Linq; +using Raven.Client.Extensions; +using Raven.Client.Documents.Operations; +using Raven.Client.Documents.Queries; + +namespace WorkflowCore.Persistence.RavenDB.Services +{ + public class WorkflowPurger : IWorkflowPurger + { + private readonly IDocumentStore _database; + + public WorkflowPurger(IDocumentStore database) + { + _database = database; + } + + public async Task PurgeWorkflows(WorkflowStatus status, DateTime olderThan) + { + await DeleteWorkflowInstances(status, olderThan); + } + + + /// + /// Delete all Workflow Documents + /// + /// + private Task DeleteWorkflowInstances(WorkflowStatus status, DateTime olderThan) + { + var utcTime = olderThan.ToUniversalTime(); + var queryToDelete = new IndexQuery { Query = $"FROM {nameof(WorkflowInstance)} where status = '{status}' and CompleteTime < '{olderThan}'" }; + return _database.Operations.SendAsync(new DeleteByQueryOperation(queryToDelete, new QueryOperationOptions { AllowStale = false })); + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/WorkflowCore.Persistence.RavenDB.csproj b/src/providers/WorkflowCore.Persistence.RavenDB/WorkflowCore.Persistence.RavenDB.csproj new file mode 100644 index 000000000..69c8e94e7 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.RavenDB/WorkflowCore.Persistence.RavenDB.csproj @@ -0,0 +1,32 @@ + + + + Workflow Core RavenDB Persistence Provider + netstandard2.0 + WorkflowCore.Persistence.RavenDB + WorkflowCore.Persistence.RavenDB + workflow;.NET;Core;state machine;WorkflowCore;RavenDB + https://github.com/danielgerlag/workflow-core + https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md + git + https://github.com/danielgerlag/workflow-core.git + false + false + false + Provides support to persist workflows running on Workflow Core to a RavenDB database. + + + + + + + + + + + + + + + + From a30b7d9ab330418bf3b651ba86d137412391854b Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Thu, 17 Dec 2020 16:48:25 -0800 Subject: [PATCH 057/342] use hashset for in-memory lock store --- .../Services/DefaultProviders/SingleNodeLockProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WorkflowCore/Services/DefaultProviders/SingleNodeLockProvider.cs b/src/WorkflowCore/Services/DefaultProviders/SingleNodeLockProvider.cs index 3d6107d66..6e920b712 100644 --- a/src/WorkflowCore/Services/DefaultProviders/SingleNodeLockProvider.cs +++ b/src/WorkflowCore/Services/DefaultProviders/SingleNodeLockProvider.cs @@ -12,7 +12,7 @@ namespace WorkflowCore.Services /// public class SingleNodeLockProvider : IDistributedLockProvider { - private List _locks = new List(); + private HashSet _locks = new HashSet(); public async Task AcquireLock(string Id, CancellationToken cancellationToken) { From 647d9b8dfbd8cbd14a3dce02c9358a0bf8efe502 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 19 Dec 2020 08:47:13 -0800 Subject: [PATCH 058/342] Revert "Add dotnet 5 support (with fixed mysql)" --- ...rkflowCore.Persistence.EntityFramework.csproj | 14 +++++++------- .../WorkflowCore.Persistence.MySQL.csproj | 12 ++++++------ .../WorkflowCore.Persistence.PostgreSQL.csproj | 16 ++++++++-------- .../SqlServerContext.cs | 12 ++++++------ .../WorkflowCore.Persistence.SqlServer.csproj | 16 ++++++++-------- .../WorkflowCore.Persistence.Sqlite.csproj | 12 ++++++------ .../WorkflowCore.QueueProviders.SqlServer.csproj | 4 ++-- .../WorkflowCore.Sample01.csproj | 14 +++++++------- .../WorkflowCore.Sample02.csproj | 6 +++--- .../WorkflowCore.Sample03.csproj | 8 ++++---- .../WorkflowCore.Sample04.csproj | 10 +++++----- .../WorkflowCore.Sample05.csproj | 2 +- .../WorkflowCore.Sample06.csproj | 2 +- .../WorkflowCore.Sample07.csproj | 4 ++-- .../WorkflowCore.Sample08.csproj | 4 ++-- .../WorkflowCore.Sample09.csproj | 4 ++-- .../WorkflowCore.Sample09s.csproj | 6 +++--- .../WorkflowCore.Sample10.csproj | 4 ++-- .../WorkflowCore.Sample11.csproj | 6 +++--- .../WorkflowCore.Sample12.csproj | 4 ++-- .../WorkflowCore.Sample13.csproj | 4 ++-- .../WorkflowCore.Sample14.csproj | 2 +- .../WorkflowCore.Sample15.csproj | 6 +++--- .../WorkflowCore.Sample16.csproj | 6 +++--- .../WorkflowCore.Sample17.csproj | 4 ++-- .../WorkflowCore.Sample18.csproj | 12 ++++++------ .../WorkflowCore.Sample19.csproj | 12 ++++++------ .../WorkflowCore.TestSample01.csproj | 4 ++-- test/ScratchPad/ScratchPad.csproj | 6 +++--- .../WorkflowCore.IntegrationTests.csproj | 8 ++++---- .../WorkflowCore.TestAssets.csproj | 2 +- .../WorkflowCore.Testing.csproj | 12 ++++++------ .../WorkflowCore.Tests.DynamoDB.csproj | 2 +- .../WorkflowCore.Tests.Elasticsearch.csproj | 2 +- .../WorkflowCore.Tests.MongoDB.csproj | 8 ++++---- .../WorkflowCore.Tests.MySQL.csproj | 4 ++-- .../WorkflowCore.Tests.PostgreSQL.csproj | 4 ++-- .../WorkflowCore.Tests.Redis.csproj | 4 ++-- .../WorkflowCore.Tests.SqlServer.csproj | 2 +- .../WorkflowCore.Tests.Sqlite.csproj | 2 +- .../WorkflowCore.UnitTests.csproj | 8 ++++---- 41 files changed, 137 insertions(+), 137 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index a08f951d9..ed8392a62 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -3,7 +3,7 @@ Workflow Core EntityFramework Core Persistence Provider Daniel Gerlag - netstandard2.1 + netstandard2.0 WorkflowCore.Persistence.EntityFramework WorkflowCore.Persistence.EntityFramework workflow;.NET;Core;state machine;WorkflowCore;EntityFramework;EntityFrameworkCore @@ -14,11 +14,11 @@ false false false - 3.3.3 + 3.1.0 Base package for Workflow-core peristence providers using entity framework - 3.3.3.0 - 3.3.3.0 - 3.3.3 + 3.1.0.0 + 3.1.0.0 + 3.1.0 @@ -26,8 +26,8 @@ - - + + diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index f40289070..a031e5fba 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -4,7 +4,7 @@ Workflow Core MySQL Persistence Provider 1.0.0 Daniel Gerlag - netstandard2.1 + netstandard2.0 WorkflowCore.Persistence.MySQL WorkflowCore.Persistence.MySQL workflow;.NET;Core;state machine;WorkflowCore;MySQL @@ -16,17 +16,17 @@ false false Provides support to persist workflows running on Workflow Core to a MySQL database. - 3.3.3 - 3.3.3.0 - 3.3.3.0 + 3.0.1 + 3.0.1.0 + 3.0.1.0 - + all runtime; build; native; contentfiles; analyzers - + diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index a5faadf44..7addc52a4 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -15,10 +15,10 @@ false false Provides support to persist workflows running on Workflow Core to a PostgreSQL database. - 3.3.3 - 3.3.3.0 - 3.3.3.0 - 3.3.3 + 3.1.0 + 3.1.0.0 + 3.1.0.0 + 3.1.0 @@ -27,12 +27,12 @@ - - - + + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs b/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs index 7383cce3e..499c10295 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs @@ -28,37 +28,37 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) protected override void ConfigureSubscriptionStorage(EntityTypeBuilder builder) { builder.ToTable("Subscription", "wfc"); - builder.Property(x => x.PersistenceId).UseIdentityColumn(); + builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); } protected override void ConfigureWorkflowStorage(EntityTypeBuilder builder) { builder.ToTable("Workflow", "wfc"); - builder.Property(x => x.PersistenceId).UseIdentityColumn(); + builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); } protected override void ConfigureExecutionPointerStorage(EntityTypeBuilder builder) { builder.ToTable("ExecutionPointer", "wfc"); - builder.Property(x => x.PersistenceId).UseIdentityColumn(); + builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); } protected override void ConfigureExecutionErrorStorage(EntityTypeBuilder builder) { builder.ToTable("ExecutionError", "wfc"); - builder.Property(x => x.PersistenceId).UseIdentityColumn(); + builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); } protected override void ConfigureExetensionAttributeStorage(EntityTypeBuilder builder) { builder.ToTable("ExtensionAttribute", "wfc"); - builder.Property(x => x.PersistenceId).UseIdentityColumn(); + builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); } protected override void ConfigureEventStorage(EntityTypeBuilder builder) { builder.ToTable("Event", "wfc"); - builder.Property(x => x.PersistenceId).UseIdentityColumn(); + builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); } } } diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index 835f26433..be52279d1 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -4,7 +4,7 @@ Workflow Core SQL Server Persistence Provider 1.8.0 Daniel Gerlag - netstandard2.1 + netstandard2.0 WorkflowCore.Persistence.SqlServer WorkflowCore.Persistence.SqlServer workflow;.NET;Core;state machine;WorkflowCore @@ -15,11 +15,11 @@ false false false - 3.3.3 + 3.1.0 Provides support to persist workflows running on Workflow Core to a SQL Server database. - 3.3.3.0 - 3.3.3.0 - 3.3.3 + 3.1.0.0 + 3.1.0.0 + 3.1.0 @@ -28,11 +28,11 @@ - - + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj index 44e1e344e..2d2789021 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj +++ b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj @@ -4,7 +4,7 @@ Workflow Core Sqlite Persistence Provider 1.5.0 Daniel Gerlag - netstandard2.1 + netstandard2.0 WorkflowCore.Persistence.Sqlite WorkflowCore.Persistence.Sqlite workflow;.NET;Core;state machine;WorkflowCore;Sqlite @@ -16,10 +16,10 @@ false false Provides support to persist workflows running on Workflow Core to a Sqlite database. - 3.3.3 - 3.3.3.0 - 3.3.3.0 - 3.3.3 + 3.1.0 + 3.1.0.0 + 3.1.0.0 + 3.1.0 @@ -28,7 +28,7 @@ - + diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj index 97b48d220..36d7cda77 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj @@ -5,7 +5,7 @@ Roberto Paterlini Queue provider for Workflow-core using SQL Server Service Broker - 1.0.4-alpha + 1.0.3-alpha @@ -20,7 +20,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj b/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj index 0e878eb0b..e4a09e491 100644 --- a/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj +++ b/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 WorkflowCore.Sample01 Exe WorkflowCore.Sample01 @@ -16,12 +16,12 @@ - - - - - - + + + + + + diff --git a/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj b/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj index 7fab128b6..0765d50c3 100644 --- a/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj +++ b/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 WorkflowCore.Sample02 Exe WorkflowCore.Sample02 @@ -11,8 +11,8 @@ - - + + diff --git a/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj b/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj index 7b332dcd9..fc4a5d4fd 100644 --- a/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj +++ b/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.0 WorkflowCore.Sample03 Exe WorkflowCore.Sample03 @@ -16,9 +16,9 @@ - - - + + + diff --git a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj index af988640d..82107b0e6 100644 --- a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj +++ b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.0 WorkflowCore.Sample04 Exe WorkflowCore.Sample04 @@ -25,13 +25,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + diff --git a/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj b/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj index 069931ef0..592fa228b 100644 --- a/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj +++ b/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj b/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj index d4c71d9aa..b61478b9e 100644 --- a/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj +++ b/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj index 2f5937f36..5ca51a866 100644 --- a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj +++ b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.0 true WorkflowCore.Sample07 Exe @@ -26,7 +26,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj b/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj index 2a556e45d..3ff429e28 100644 --- a/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj +++ b/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.0 WorkflowCore.Sample08 Exe WorkflowCore.Sample08 @@ -21,7 +21,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj b/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj index bc16eb974..6f75a0d7d 100644 --- a/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj +++ b/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.1 + netcoreapp3.0 - + diff --git a/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj b/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj index bc16eb974..e569ec895 100644 --- a/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj +++ b/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj @@ -1,12 +1,12 @@ - + Exe - netcoreapp3.1 + netcoreapp3.0 - + diff --git a/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj b/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj index bc16eb974..6f75a0d7d 100644 --- a/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj +++ b/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.1 + netcoreapp3.0 - + diff --git a/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj b/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj index 5a8923eeb..b6454f6a2 100644 --- a/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj +++ b/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj @@ -2,12 +2,12 @@ Exe - netcoreapp3.1 + netcoreapp2.2 - - + + diff --git a/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj b/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj index 5b030fb75..9879baab2 100644 --- a/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj +++ b/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.1 + netcoreapp3.0 - + diff --git a/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj b/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj index 7f814f488..dbe49166e 100644 --- a/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj +++ b/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.1 + netcoreapp2.2 - + diff --git a/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj b/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj index 974472a25..fef8173cc 100644 --- a/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj +++ b/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + netcoreapp2.2 diff --git a/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj b/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj index 79ed2ba57..c63fbd792 100644 --- a/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj +++ b/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj @@ -2,12 +2,12 @@ Exe - netcoreapp3.1 + netcoreapp2.2 - - + + diff --git a/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj b/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj index 79ed2ba57..c63fbd792 100644 --- a/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj +++ b/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj @@ -2,12 +2,12 @@ Exe - netcoreapp3.1 + netcoreapp2.2 - - + + diff --git a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj index 766fc8e0c..26933096d 100644 --- a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj +++ b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.1 + netcoreapp3.0 - + diff --git a/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj b/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj index 5f9b64824..660b47511 100644 --- a/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj +++ b/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj @@ -1,15 +1,15 @@ - + Exe - netcoreapp3.1 + netcoreapp3.0 - - - - + + + + diff --git a/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj b/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj index 0f169bcc8..b2a7796c3 100644 --- a/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj +++ b/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj @@ -1,15 +1,15 @@ - + Exe - netcoreapp3.1 + netcoreapp3.0 - - - - + + + + diff --git a/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj b/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj index 71454dc11..282fdbb15 100644 --- a/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj +++ b/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj @@ -1,12 +1,12 @@  - netcoreapp3.1 + netcoreapp2.2 - + diff --git a/test/ScratchPad/ScratchPad.csproj b/test/ScratchPad/ScratchPad.csproj index 4da4684ed..4fb61dd24 100644 --- a/test/ScratchPad/ScratchPad.csproj +++ b/test/ScratchPad/ScratchPad.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.0 ScratchPad Exe ScratchPad @@ -11,8 +11,8 @@ - - + + diff --git a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj index f7634e8a9..971f10c57 100644 --- a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj +++ b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 WorkflowCore.IntegrationTests WorkflowCore.IntegrationTests true @@ -21,10 +21,10 @@ - - + + - + diff --git a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj index aeeb3d614..12da1f57b 100644 --- a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj +++ b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + netstandard2.0 WorkflowCore.TestAssets WorkflowCore.TestAssets false diff --git a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj index 22b68fb2f..32f9c1363 100644 --- a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj +++ b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj @@ -2,16 +2,16 @@ netstandard2.0 - 2.3.1 - 2.3.1.0 - 2.3.1.0 + 2.3.0 + 2.3.0.0 + 2.3.0.0 Facilitates testing of workflows built on Workflow-Core - - - + + + diff --git a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj index f275a05cf..c2563b8b2 100644 --- a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj +++ b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + netcoreapp2.2 false diff --git a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj index 0ed01e311..168be514f 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj +++ b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 false diff --git a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj index 1523f31ea..bec4d8561 100644 --- a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj +++ b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 WorkflowCore.Tests.MongoDB WorkflowCore.Tests.MongoDB true @@ -22,9 +22,9 @@ - - - + + + diff --git a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj index 66a792fe5..a255e01d6 100644 --- a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj +++ b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1 + netcoreapp2.2 false diff --git a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj index 2fefbdea8..1cc7d56bd 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj +++ b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.0 WorkflowCore.Tests.PostgreSQL WorkflowCore.Tests.PostgreSQL true @@ -21,7 +21,7 @@ - + diff --git a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj index 76857bc6d..c5ee9a6f8 100644 --- a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj +++ b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1 + netcoreapp2.2 false diff --git a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj index 497293aaf..011714983 100644 --- a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj +++ b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 diff --git a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj index 9598398f4..9ce1b77cd 100644 --- a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj +++ b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 diff --git a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj index 5ec1e2ff1..294adbd23 100644 --- a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj +++ b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.2 WorkflowCore.UnitTests WorkflowCore.UnitTests true @@ -20,9 +20,9 @@ - - - + + + From c1f67abef0ef4570e57c83a51222c0fbc061dd64 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 19 Dec 2020 08:50:17 -0800 Subject: [PATCH 059/342] issue 682 --- .../ErrorHandlers/CompensateHandler.cs | 14 ++- .../MultistepCompensationScenario2.cs | 97 +++++++++++++++++++ 2 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 test/WorkflowCore.IntegrationTests/Scenarios/MultistepCompensationScenario2.cs diff --git a/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs index 2023a59f1..dfc13af36 100644 --- a/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs @@ -29,7 +29,8 @@ public void Handle(WorkflowInstance workflow, WorkflowDefinition def, ExecutionP { var scope = new Stack(exceptionPointer.Scope.Reverse()); scope.Push(exceptionPointer.Id); - + ExecutionPointer compensationPointer = null; + while (scope.Any()) { var pointerId = scope.Pop(); @@ -63,13 +64,18 @@ public void Handle(WorkflowInstance workflow, WorkflowDefinition def, ExecutionP scopePointer.EndTime = _datetimeProvider.UtcNow; scopePointer.Status = PointerStatus.Failed; - ExecutionPointer compensationPointer = null; - if (scopeStep.CompensationStepId.HasValue) { scopePointer.Status = PointerStatus.Compensated; - compensationPointer = _pointerFactory.BuildCompensationPointer(def, scopePointer, exceptionPointer, scopeStep.CompensationStepId.Value); + var nextCompensationPointer = _pointerFactory.BuildCompensationPointer(def, scopePointer, exceptionPointer, scopeStep.CompensationStepId.Value); + if (compensationPointer != null) + { + nextCompensationPointer.Active = false; + nextCompensationPointer.Status = PointerStatus.PendingPredecessor; + nextCompensationPointer.PredecessorId = compensationPointer.Id; + } + compensationPointer = nextCompensationPointer; workflow.ExecutionPointers.Add(compensationPointer); if (resume) diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/MultistepCompensationScenario2.cs b/test/WorkflowCore.IntegrationTests/Scenarios/MultistepCompensationScenario2.cs new file mode 100644 index 000000000..ec0888501 --- /dev/null +++ b/test/WorkflowCore.IntegrationTests/Scenarios/MultistepCompensationScenario2.cs @@ -0,0 +1,97 @@ +using System; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using Xunit; +using FluentAssertions; +using WorkflowCore.Testing; + +namespace WorkflowCore.IntegrationTests.Scenarios +{ + public class MultistepCompensationScenario2 : WorkflowTest + { + public class Workflow : IWorkflow + { + public static int CompensationCounter = 0; + public static int Compensation1_1Fired = 0; + public static int Compensation1_2Fired = 0; + public static int Compensation2_1Fired = 0; + public static int Compensation2_2Fired = 0; + public static int Compensation3Fired = 0; + public static int Compensation4Fired = 0; + + + public string Id => "MultistepCompensationScenario2"; + public int Version => 1; + public void Build(IWorkflowBuilder builder) + { + builder + .StartWith(context => ExecutionResult.Next()) + .Saga(x => x + .StartWith(context => ExecutionResult.Next()) + .CompensateWithSequence(context => context.StartWith(c => + { + CompensationCounter++; + Compensation1_1Fired = CompensationCounter; + }) + .Then(c => + { + CompensationCounter++; + Compensation1_2Fired = CompensationCounter; + })) + .If(c => true).Do(then => then + .Then(context => ExecutionResult.Next()) + .CompensateWithSequence(context => context.StartWith(c => + { + CompensationCounter++; + Compensation2_1Fired = CompensationCounter; + }).Then(c => + { + CompensationCounter++; + Compensation2_2Fired = CompensationCounter; + })) + .Then(context => ExecutionResult.Next()) + .CompensateWith(context => + { + CompensationCounter++; + Compensation3Fired = CompensationCounter; + }) + .Then(context => throw new Exception()) + .CompensateWith(context => + { + CompensationCounter++; + Compensation4Fired = CompensationCounter; + })) + ); + } + } + + public MultistepCompensationScenario2() + { + Setup(); + Workflow.Compensation1_1Fired = -1; + Workflow.Compensation1_2Fired = -1; + Workflow.Compensation2_1Fired = -1; + Workflow.Compensation2_2Fired = -1; + Workflow.Compensation3Fired = -1; + Workflow.Compensation4Fired = -1; + Workflow.CompensationCounter = 0; + } + + [Fact] + public void MultiCompensationStepOrder() + { + var workflowId = StartWorkflow(null); + WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); + + GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); + UnhandledStepErrors.Count.Should().Be(1); + + Workflow.Compensation1_2Fired.Should().Be(6); + Workflow.Compensation1_1Fired.Should().Be(5); + Workflow.Compensation2_2Fired.Should().Be(4); + Workflow.Compensation2_1Fired.Should().Be(3); + Workflow.Compensation3Fired.Should().Be(2); + Workflow.Compensation4Fired.Should().Be(1); + } + } +} From 0e43c75d9779369482bb2d0ed239fee947089975 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 19 Dec 2020 08:58:53 -0800 Subject: [PATCH 060/342] bump version --- src/WorkflowCore/WorkflowCore.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 36e9f45c1..24da88bcc 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.3.3 - 3.3.3.0 - 3.3.3.0 + 3.3.4 + 3.3.4.0 + 3.3.4.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.3.3 + 3.3.4 From f52d8fd929d9dc0cdfbf1a576b47b933bca8f5fe Mon Sep 17 00:00:00 2001 From: Xavid Ramirez Date: Mon, 28 Dec 2020 21:53:34 -0600 Subject: [PATCH 061/342] adding readme to project --- .../README.md | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/providers/WorkflowCore.Persistence.RavenDB/README.md diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/README.md b/src/providers/WorkflowCore.Persistence.RavenDB/README.md new file mode 100644 index 000000000..fc4835e49 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.RavenDB/README.md @@ -0,0 +1,31 @@ + +# RavenDB Persistence provider for Workflow Core + +Provides support to persist workflows running on [Workflow Core](../../README.md) to a RavenDB database. + +## Installing + +Install the NuGet package "WorkflowCore.Persistence.RavenDB" + +``` +PM> Install-Package WorkflowCore.Persistence.RavenDB +``` + +## Usage + +Compose your RavenStoreOptions using the model provided by the library. + +```C# +var options = new RavenStoreOptions { + ServerUrl = "https://ravendbserver.domain.com:8080", + DatabaseName = "TestDatabase", + CertificatePath = System.IO.Path.Combine(AppContext.BaseDirectory, "Resources/servercert.pfx"), + CertificatePassword = "CertificatePassword" +} +``` + +Use the `.UseRavenDB` extension method when building your service provider, passing in the options you configured for the RavenDB store. + +```C# +services.AddWorkflow(x => x.UseRavenDB(options)); +``` From ccdddf3aaf0ef29f301be142d5208f794d0a68c5 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 29 Dec 2020 18:20:10 -0800 Subject: [PATCH 062/342] Create dotnet.yml --- .github/workflows/dotnet.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/dotnet.yml diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml new file mode 100644 index 000000000..d686bebf7 --- /dev/null +++ b/.github/workflows/dotnet.yml @@ -0,0 +1,25 @@ +name: .NET + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 3.1.301 + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Test + run: dotnet test --no-build --verbosity normal From a59e4db74a7be3f2da8d3c6ff41b67ff176f35cd Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 29 Dec 2020 18:33:38 -0800 Subject: [PATCH 063/342] Update dotnet.yml --- .github/workflows/dotnet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index d686bebf7..01e08fb1b 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -9,7 +9,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: windows-latest steps: - uses: actions/checkout@v2 From 6c5fea10f23609e1cbaf49c7f4eb489629ed41d9 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 29 Dec 2020 18:39:59 -0800 Subject: [PATCH 064/342] github actions --- .github/workflows/dotnet.yml | 2 +- test/ScratchPad/Properties/Resources.resx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 01e08fb1b..d686bebf7 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -9,7 +9,7 @@ on: jobs: build: - runs-on: windows-latest + runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/test/ScratchPad/Properties/Resources.resx b/test/ScratchPad/Properties/Resources.resx index 7a5a7544d..421b272c5 100644 --- a/test/ScratchPad/Properties/Resources.resx +++ b/test/ScratchPad/Properties/Resources.resx @@ -119,6 +119,6 @@ - ..\helloworld.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + ..\HelloWorld.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 \ No newline at end of file From 3e175e0d8bcca35b778450657a809d4899a8d25a Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 29 Dec 2020 18:47:00 -0800 Subject: [PATCH 065/342] update test project framework --- .../WorkflowCore.IntegrationTests.csproj | 2 +- .../WorkflowCore.Tests.DynamoDB.csproj | 2 +- .../WorkflowCore.Tests.Elasticsearch.csproj | 2 +- .../WorkflowCore.Tests.MongoDB.csproj | 2 +- test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj | 2 +- .../WorkflowCore.Tests.PostgreSQL.csproj | 2 +- test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj | 2 +- .../WorkflowCore.Tests.SqlServer.csproj | 2 +- test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj | 2 +- test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj index 971f10c57..f52ee0ba1 100644 --- a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj +++ b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 WorkflowCore.IntegrationTests WorkflowCore.IntegrationTests true diff --git a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj index c2563b8b2..f275a05cf 100644 --- a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj +++ b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.1 false diff --git a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj index 168be514f..0ed01e311 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj +++ b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 false diff --git a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj index bec4d8561..a76f2b513 100644 --- a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj +++ b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 WorkflowCore.Tests.MongoDB WorkflowCore.Tests.MongoDB true diff --git a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj index a255e01d6..ff53c72b2 100644 --- a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj +++ b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.1 false diff --git a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj index 1cc7d56bd..c58b3243f 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj +++ b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 WorkflowCore.Tests.PostgreSQL WorkflowCore.Tests.PostgreSQL true diff --git a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj index c5ee9a6f8..af4f4117d 100644 --- a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj +++ b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.1 false diff --git a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj index 011714983..497293aaf 100644 --- a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj +++ b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 diff --git a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj index 9ce1b77cd..9598398f4 100644 --- a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj +++ b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 diff --git a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj index 294adbd23..81ceeb3b1 100644 --- a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj +++ b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 WorkflowCore.UnitTests WorkflowCore.UnitTests true From 956632b5836b452c189e6778183da01819c2e8cc Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 29 Dec 2020 19:06:31 -0800 Subject: [PATCH 066/342] tests --- .../SearchIndexTests.cs | 1 + .../ElasticsearchDockerSetup.cs | 2 +- .../Scenarios/MongoDynamicDataScenario.cs | 16 ---------------- 3 files changed, 2 insertions(+), 17 deletions(-) delete mode 100644 test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDynamicDataScenario.cs diff --git a/test/WorkflowCore.IntegrationTests/SearchIndexTests.cs b/test/WorkflowCore.IntegrationTests/SearchIndexTests.cs index 8c834f82f..d244ff7c3 100644 --- a/test/WorkflowCore.IntegrationTests/SearchIndexTests.cs +++ b/test/WorkflowCore.IntegrationTests/SearchIndexTests.cs @@ -23,6 +23,7 @@ protected SearchIndexTests() foreach (var item in BuildTestData()) Subject.IndexWorkflow(item).Wait(); + System.Threading.Thread.Sleep(1000); } protected IEnumerable BuildTestData() diff --git a/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs b/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs index e79779466..aef37beaa 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs +++ b/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs @@ -43,7 +43,7 @@ public override bool TestReady() } [CollectionDefinition("Elasticsearch collection")] - public class DynamoDbCollection : ICollectionFixture + public class ElasticsearchCollection : ICollectionFixture { } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDynamicDataScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDynamicDataScenario.cs deleted file mode 100644 index 456f0a0f1..000000000 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDynamicDataScenario.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using Microsoft.Extensions.DependencyInjection; -using WorkflowCore.IntegrationTests.Scenarios; -using Xunit; - -namespace WorkflowCore.Tests.MongoDB.Scenarios -{ - [Collection("Mongo collection")] - public class MongoDynamicDataScenario : DynamicDataIOScenario - { - protected override void ConfigureServices(IServiceCollection services) - { - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); - } - } -} From b72e2b038fb81718bfe474a08db03d7004a41771 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 30 Dec 2020 07:20:41 -0800 Subject: [PATCH 067/342] test setup --- test/Docker.Testify/DockerSetup.cs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/test/Docker.Testify/DockerSetup.cs b/test/Docker.Testify/DockerSetup.cs index 0bf7055df..f5dc0423a 100644 --- a/test/Docker.Testify/DockerSetup.cs +++ b/test/Docker.Testify/DockerSetup.cs @@ -30,6 +30,8 @@ public abstract class DockerSetup : IDisposable protected readonly DockerClient docker; protected string containerId; + private static object Lock = new object(); + protected DockerSetup() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -122,21 +124,24 @@ public void Dispose() private int GetFreePort() { - const int startRange = 1000; - const int endRange = 10000; - var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); - var tcpPorts = ipGlobalProperties.GetActiveTcpListeners(); - var udpPorts = ipGlobalProperties.GetActiveUdpListeners(); + lock (Lock) + { + const int startRange = 1000; + const int endRange = 10000; + var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); + var tcpPorts = ipGlobalProperties.GetActiveTcpListeners(); + var udpPorts = ipGlobalProperties.GetActiveUdpListeners(); - var result = startRange; + var result = startRange; - while (((tcpPorts.Any(x => x.Port == result)) || (udpPorts.Any(x => x.Port == result))) && result <= endRange) - result++; + while (((tcpPorts.Any(x => x.Port == result)) || (udpPorts.Any(x => x.Port == result))) && result <= endRange) + result++; - if (result > endRange) - throw new PortsInUseException(); + if (result > endRange) + throw new PortsInUseException(); - return result; + return result; + } } } } From 301466b05808c2040bd774defdad22eefb78729a Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 30 Dec 2020 07:31:18 -0800 Subject: [PATCH 068/342] test setup --- .../WorkflowCore.TestSample01.csproj | 2 +- test/Docker.Testify/DockerSetup.cs | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj b/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj index 282fdbb15..46df42954 100644 --- a/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj +++ b/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 diff --git a/test/Docker.Testify/DockerSetup.cs b/test/Docker.Testify/DockerSetup.cs index f5dc0423a..278567231 100644 --- a/test/Docker.Testify/DockerSetup.cs +++ b/test/Docker.Testify/DockerSetup.cs @@ -30,7 +30,7 @@ public abstract class DockerSetup : IDisposable protected readonly DockerClient docker; protected string containerId; - private static object Lock = new object(); + private static HashSet UsedPorts = new HashSet(); protected DockerSetup() { @@ -124,7 +124,7 @@ public void Dispose() private int GetFreePort() { - lock (Lock) + lock (UsedPorts) { const int startRange = 1000; const int endRange = 10000; @@ -134,11 +134,13 @@ private int GetFreePort() var result = startRange; - while (((tcpPorts.Any(x => x.Port == result)) || (udpPorts.Any(x => x.Port == result))) && result <= endRange) + while (((tcpPorts.Any(x => x.Port == result)) || (udpPorts.Any(x => x.Port == result))) && result <= endRange && !UsedPorts.Contains(result)) result++; if (result > endRange) throw new PortsInUseException(); + + UsedPorts.Add(result); return result; } From 4b8fbb9cd106b594965e1cbb88c56c9c0941b311 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 30 Dec 2020 08:02:13 -0800 Subject: [PATCH 069/342] docker test timeout --- test/Docker.Testify/DockerSetup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Docker.Testify/DockerSetup.cs b/test/Docker.Testify/DockerSetup.cs index 278567231..8763d8855 100644 --- a/test/Docker.Testify/DockerSetup.cs +++ b/test/Docker.Testify/DockerSetup.cs @@ -20,7 +20,7 @@ public abstract class DockerSetup : IDisposable public abstract int InternalPort { get; } public virtual string ImageTag => "latest"; - public virtual TimeSpan TimeOut => TimeSpan.FromSeconds(30); + public virtual TimeSpan TimeOut => TimeSpan.FromSeconds(60); public virtual IList EnvironmentVariables => new List(); public int ExternalPort { get; } From 2069c15258c8dfaff0da457d73fcc87df2d4ca13 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 30 Dec 2020 08:13:09 -0800 Subject: [PATCH 070/342] test setup --- test/Docker.Testify/DockerSetup.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Docker.Testify/DockerSetup.cs b/test/Docker.Testify/DockerSetup.cs index 8763d8855..7d5ae9bc3 100644 --- a/test/Docker.Testify/DockerSetup.cs +++ b/test/Docker.Testify/DockerSetup.cs @@ -126,8 +126,8 @@ private int GetFreePort() { lock (UsedPorts) { - const int startRange = 1000; - const int endRange = 10000; + const int startRange = 10002; + const int endRange = 15000; var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); var tcpPorts = ipGlobalProperties.GetActiveTcpListeners(); var udpPorts = ipGlobalProperties.GetActiveUdpListeners(); From 47cb5d0b88e2f7ff3bc35e418a4bcd3353b8931e Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 30 Dec 2020 08:50:45 -0800 Subject: [PATCH 071/342] dynamodb tests docker setup timeout --- test/WorkflowCore.Tests.DynamoDB/DynamoDbDockerSetup.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/WorkflowCore.Tests.DynamoDB/DynamoDbDockerSetup.cs b/test/WorkflowCore.Tests.DynamoDB/DynamoDbDockerSetup.cs index a166ec804..6e52c238e 100644 --- a/test/WorkflowCore.Tests.DynamoDB/DynamoDbDockerSetup.cs +++ b/test/WorkflowCore.Tests.DynamoDB/DynamoDbDockerSetup.cs @@ -20,6 +20,7 @@ public class DynamoDbDockerSetup : DockerSetup public override string ImageName => @"amazon/dynamodb-local"; public override int InternalPort => 8000; + public override TimeSpan TimeOut => TimeSpan.FromSeconds(120); public override void PublishConnectionInfo() { From 168cabab85763c1aef8a952d534f4d780c72d872 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 30 Dec 2020 09:08:12 -0800 Subject: [PATCH 072/342] Update dotnet.yml --- .github/workflows/dotnet.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index d686bebf7..29100399e 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -21,5 +21,15 @@ jobs: run: dotnet restore - name: Build run: dotnet build --no-restore - - name: Test - run: dotnet test --no-build --verbosity normal + - name: Unit Tests + run: dotnet test test/WorkflowCore.UnitTests --no-build --verbosity normal + - name: Integration Tests + run: dotnet test test/WorkflowCore.IntegrationTests --no-build --verbosity normal + - name: PostgreSQL Tests + run: dotnet test test/WorkflowCore.Tests.PostgreSQL --no-build --verbosity normal + - name: Redis Tests + run: dotnet test test/WorkflowCore.Tests.Redis --no-build --verbosity normal + - name: SQL Server Tests + run: dotnet test test/WorkflowCore.Tests.SqlServer --no-build --verbosity normal + - name: Elasticsearch Tests + run: dotnet test test/WorkflowCore.Tests.Elasticsearch --no-build --verbosity normal From 1118bad9eed70d850ded700635a191a5e1c1e652 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Thu, 31 Dec 2020 09:15:37 -0800 Subject: [PATCH 073/342] bump versions --- src/WorkflowCore.DSL/WorkflowCore.DSL.csproj | 3 ++- src/WorkflowCore/WorkflowCore.csproj | 9 ++++----- .../Services/WorkflowPurger.cs | 1 - .../Services/DataObjectSerializer.cs | 1 - 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj b/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj index 3670d6553..689d95119 100644 --- a/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj +++ b/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 3.3.0 + 3.3.1 DSL extenstion for Workflow Core provding support for JSON and YAML workflow definitions. Daniel Gerlag @@ -15,6 +15,7 @@ + diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 24da88bcc..2f465db0d 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.3.4 - 3.3.4.0 - 3.3.4.0 + 3.3.5 + 3.3.5.0 + 3.3.5.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.3.4 + 3.3.5 @@ -30,7 +30,6 @@ - diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowPurger.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowPurger.cs index e75caaed0..31384be84 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowPurger.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowPurger.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using System.Linq.Dynamic.Core; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using WorkflowCore.Interface; diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs index a01a770d9..894b58ed1 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Linq.Dynamic.Core; using System.Linq.Expressions; using System.Threading.Tasks; using WorkflowCore.Models; From ad4b6dbd50802c24fbde95d9f07de6b56d9a3176 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Thu, 31 Dec 2020 09:17:42 -0800 Subject: [PATCH 074/342] bump versions --- .../WorkflowCore.Persistence.EntityFramework.csproj | 8 ++++---- .../WorkflowCore.Persistence.MongoDB.csproj | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index ed8392a62..b126a9c23 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -14,11 +14,11 @@ false false false - 3.1.0 + 3.1.1 Base package for Workflow-core peristence providers using entity framework - 3.1.0.0 - 3.1.0.0 - 3.1.0 + 3.1.1.0 + 3.1.1.0 + 3.1.1 diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj index b762cb930..b6e6204c0 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj +++ b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj @@ -14,11 +14,11 @@ false false false - 3.0.2 + 3.0.3 Provides support to persist workflows running on Workflow Core to a MongoDB database. - 3.0.2.0 - 3.0.2.0 - 3.0.2 + 3.0.3.0 + 3.0.3.0 + 3.0.3 From fdbd1f390d206b264eda9074d54bf2d5d4ebc59f Mon Sep 17 00:00:00 2001 From: Fu Yu Date: Wed, 6 Jan 2021 15:45:27 +1100 Subject: [PATCH 075/342] SqlServer Provider: replace UseSqlServerIdentityColumn with UseIdentityColumn --- .../SqlServerContext.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs b/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs index 499c10295..7383cce3e 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs @@ -28,37 +28,37 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) protected override void ConfigureSubscriptionStorage(EntityTypeBuilder builder) { builder.ToTable("Subscription", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureWorkflowStorage(EntityTypeBuilder builder) { builder.ToTable("Workflow", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureExecutionPointerStorage(EntityTypeBuilder builder) { builder.ToTable("ExecutionPointer", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureExecutionErrorStorage(EntityTypeBuilder builder) { builder.ToTable("ExecutionError", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureExetensionAttributeStorage(EntityTypeBuilder builder) { builder.ToTable("ExtensionAttribute", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } protected override void ConfigureEventStorage(EntityTypeBuilder builder) { builder.ToTable("Event", "wfc"); - builder.Property(x => x.PersistenceId).UseSqlServerIdentityColumn(); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); } } } From 596d167e30a030fd92601dd1765803db0b195863 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 8 Jan 2021 20:51:50 -0800 Subject: [PATCH 076/342] bump version --- .../WorkflowCore.Persistence.SqlServer.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index be52279d1..fe5c32f81 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -15,11 +15,11 @@ false false false - 3.1.0 + 3.1.1 Provides support to persist workflows running on Workflow Core to a SQL Server database. - 3.1.0.0 - 3.1.0.0 - 3.1.0 + 3.1.1.0 + 3.1.1.0 + 3.1.1 From 68a38035c210423fbd6c9f93d3cb34ce53c97943 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 9 Jan 2021 09:53:06 -0800 Subject: [PATCH 077/342] fixes for break EF core 5 changes --- ...WorkflowCore.Persistence.PostgreSQL.csproj | 16 +- .../20210109172432_EFCore5.Designer.cs | 338 ++++++++++++++++++ .../Migrations/20210109172432_EFCore5.cs | 17 + ...lServerPersistenceProviderModelSnapshot.cs | 138 +++---- .../WorkflowCore.Persistence.SqlServer.csproj | 16 +- .../WorkflowCore.Persistence.Sqlite.csproj | 12 +- .../WorkflowCore.Sample03.csproj | 4 +- .../WorkflowCore.Sample04.csproj | 15 +- .../WorkflowCore.Sample07.csproj | 4 +- .../WorkflowCore.Sample13.csproj | 2 +- .../WorkflowCore.Sample14.csproj | 2 +- .../WorkflowCore.Sample17.csproj | 4 +- test/ScratchPad/ScratchPad.csproj | 2 +- .../WorkflowCore.Tests.PostgreSQL.csproj | 2 +- 14 files changed, 469 insertions(+), 103 deletions(-) create mode 100644 src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20210109172432_EFCore5.Designer.cs create mode 100644 src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20210109172432_EFCore5.cs diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index 7addc52a4..bcebe0247 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -15,10 +15,10 @@ false false Provides support to persist workflows running on Workflow Core to a PostgreSQL database. - 3.1.0 - 3.1.0.0 - 3.1.0.0 - 3.1.0 + 3.3.0 + 3.3.0.0 + 3.3.0.0 + 3.3.0 @@ -27,12 +27,12 @@ - - - + + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20210109172432_EFCore5.Designer.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20210109172432_EFCore5.Designer.cs new file mode 100644 index 000000000..2fe0f62d2 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20210109172432_EFCore5.Designer.cs @@ -0,0 +1,338 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using WorkflowCore.Persistence.SqlServer; + +namespace WorkflowCore.Persistence.SqlServer.Migrations +{ + [DbContext(typeof(SqlServerContext))] + [Migration("20210109172432_EFCore5")] + partial class EFCore5 + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseIdentityColumns() + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.1"); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("EventData") + .HasColumnType("nvarchar(max)"); + + b.Property("EventId") + .HasColumnType("uniqueidentifier"); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("EventTime") + .HasColumnType("datetime2"); + + b.Property("IsProcessed") + .HasColumnType("bit"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventId") + .IsUnique(); + + b.HasIndex("EventTime"); + + b.HasIndex("IsProcessed"); + + b.HasIndex("EventName", "EventKey"); + + b.ToTable("Event", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionError", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("ErrorTime") + .HasColumnType("datetime2"); + + b.Property("ExecutionPointerId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Message") + .HasColumnType("nvarchar(max)"); + + b.Property("WorkflowId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("PersistenceId"); + + b.ToTable("ExecutionError", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("Active") + .HasColumnType("bit"); + + b.Property("Children") + .HasColumnType("nvarchar(max)"); + + b.Property("ContextItem") + .HasColumnType("nvarchar(max)"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("EventData") + .HasColumnType("nvarchar(max)"); + + b.Property("EventKey") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("EventName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("EventPublished") + .HasColumnType("bit"); + + b.Property("Id") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Outcome") + .HasColumnType("nvarchar(max)"); + + b.Property("PersistenceData") + .HasColumnType("nvarchar(max)"); + + b.Property("PredecessorId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Scope") + .HasColumnType("nvarchar(max)"); + + b.Property("SleepUntil") + .HasColumnType("datetime2"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("StepId") + .HasColumnType("int"); + + b.Property("StepName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("WorkflowId") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("WorkflowId"); + + b.ToTable("ExecutionPointer", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("AttributeKey") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("AttributeValue") + .HasColumnType("nvarchar(max)"); + + b.Property("ExecutionPointerId") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecutionPointerId"); + + b.ToTable("ExtensionAttribute", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ExecutionPointerId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ExternalToken") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ExternalTokenExpiry") + .HasColumnType("datetime2"); + + b.Property("ExternalWorkerId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("StepId") + .HasColumnType("int"); + + b.Property("SubscribeAsOf") + .HasColumnType("datetime2"); + + b.Property("SubscriptionData") + .HasColumnType("nvarchar(max)"); + + b.Property("SubscriptionId") + .HasMaxLength(200) + .HasColumnType("uniqueidentifier"); + + b.Property("WorkflowId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventKey"); + + b.HasIndex("EventName"); + + b.HasIndex("SubscriptionId") + .IsUnique(); + + b.ToTable("Subscription", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .UseIdentityColumn(); + + b.Property("CompleteTime") + .HasColumnType("datetime2"); + + b.Property("CreateTime") + .HasColumnType("datetime2"); + + b.Property("Data") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("InstanceId") + .HasMaxLength(200) + .HasColumnType("uniqueidentifier"); + + b.Property("NextExecution") + .HasColumnType("bigint"); + + b.Property("Reference") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Version") + .HasColumnType("int"); + + b.Property("WorkflowDefinitionId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("InstanceId") + .IsUnique(); + + b.HasIndex("NextExecution"); + + b.ToTable("Workflow", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", "Workflow") + .WithMany("ExecutionPointers") + .HasForeignKey("WorkflowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Workflow"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", "ExecutionPointer") + .WithMany("ExtensionAttributes") + .HasForeignKey("ExecutionPointerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ExecutionPointer"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Navigation("ExtensionAttributes"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Navigation("ExecutionPointers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20210109172432_EFCore5.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20210109172432_EFCore5.cs new file mode 100644 index 000000000..e36775325 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20210109172432_EFCore5.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace WorkflowCore.Persistence.SqlServer.Migrations +{ + public partial class EFCore5 : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs index 8ecddd28e..1b5c63cc1 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs @@ -15,18 +15,16 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.0") + .UseIdentityColumns() .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasAnnotation("ProductVersion", "5.0.1"); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => { b.Property("PersistenceId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .HasAnnotation("SqlServer:IdentityIncrement", 1) - .HasAnnotation("SqlServer:IdentitySeed", 1) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .UseIdentityColumn(); b.Property("EventData") .HasColumnType("nvarchar(max)"); @@ -35,12 +33,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uniqueidentifier"); b.Property("EventKey") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); b.Property("EventName") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); b.Property("EventTime") .HasColumnType("datetime2"); @@ -59,7 +57,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventName", "EventKey"); - b.ToTable("Event","wfc"); + b.ToTable("Event", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionError", b => @@ -67,27 +65,25 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PersistenceId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .HasAnnotation("SqlServer:IdentityIncrement", 1) - .HasAnnotation("SqlServer:IdentitySeed", 1) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .UseIdentityColumn(); b.Property("ErrorTime") .HasColumnType("datetime2"); b.Property("ExecutionPointerId") - .HasColumnType("nvarchar(100)") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); b.Property("Message") .HasColumnType("nvarchar(max)"); b.Property("WorkflowId") - .HasColumnType("nvarchar(100)") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); b.HasKey("PersistenceId"); - b.ToTable("ExecutionError","wfc"); + b.ToTable("ExecutionError", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => @@ -95,9 +91,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PersistenceId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .HasAnnotation("SqlServer:IdentityIncrement", 1) - .HasAnnotation("SqlServer:IdentitySeed", 1) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .UseIdentityColumn(); b.Property("Active") .HasColumnType("bit"); @@ -115,19 +109,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(max)"); b.Property("EventKey") - .HasColumnType("nvarchar(100)") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); b.Property("EventName") - .HasColumnType("nvarchar(100)") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); b.Property("EventPublished") .HasColumnType("bit"); b.Property("Id") - .HasColumnType("nvarchar(50)") - .HasMaxLength(50); + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); b.Property("Outcome") .HasColumnType("nvarchar(max)"); @@ -136,8 +130,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(max)"); b.Property("PredecessorId") - .HasColumnType("nvarchar(100)") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); b.Property("RetryCount") .HasColumnType("int"); @@ -158,8 +152,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("int"); b.Property("StepName") - .HasColumnType("nvarchar(100)") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); b.Property("WorkflowId") .HasColumnType("bigint"); @@ -168,7 +162,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("WorkflowId"); - b.ToTable("ExecutionPointer","wfc"); + b.ToTable("ExecutionPointer", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => @@ -176,13 +170,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PersistenceId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .HasAnnotation("SqlServer:IdentityIncrement", 1) - .HasAnnotation("SqlServer:IdentitySeed", 1) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .UseIdentityColumn(); b.Property("AttributeKey") - .HasColumnType("nvarchar(100)") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); b.Property("AttributeValue") .HasColumnType("nvarchar(max)"); @@ -194,7 +186,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ExecutionPointerId"); - b.ToTable("ExtensionAttribute","wfc"); + b.ToTable("ExtensionAttribute", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => @@ -202,32 +194,30 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PersistenceId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .HasAnnotation("SqlServer:IdentityIncrement", 1) - .HasAnnotation("SqlServer:IdentitySeed", 1) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .UseIdentityColumn(); b.Property("EventKey") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); b.Property("EventName") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); b.Property("ExecutionPointerId") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); b.Property("ExternalToken") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); b.Property("ExternalTokenExpiry") .HasColumnType("datetime2"); b.Property("ExternalWorkerId") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); b.Property("StepId") .HasColumnType("int"); @@ -239,12 +229,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(max)"); b.Property("SubscriptionId") - .HasColumnType("uniqueidentifier") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("uniqueidentifier"); b.Property("WorkflowId") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); b.HasKey("PersistenceId"); @@ -255,7 +245,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("SubscriptionId") .IsUnique(); - b.ToTable("Subscription","wfc"); + b.ToTable("Subscription", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => @@ -263,9 +253,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PersistenceId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .HasAnnotation("SqlServer:IdentityIncrement", 1) - .HasAnnotation("SqlServer:IdentitySeed", 1) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .UseIdentityColumn(); b.Property("CompleteTime") .HasColumnType("datetime2"); @@ -277,19 +265,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(max)"); b.Property("Description") - .HasColumnType("nvarchar(500)") - .HasMaxLength(500); + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); b.Property("InstanceId") - .HasColumnType("uniqueidentifier") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("uniqueidentifier"); b.Property("NextExecution") .HasColumnType("bigint"); b.Property("Reference") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); b.Property("Status") .HasColumnType("int"); @@ -298,8 +286,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("int"); b.Property("WorkflowDefinitionId") - .HasColumnType("nvarchar(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); b.HasKey("PersistenceId"); @@ -308,7 +296,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("NextExecution"); - b.ToTable("Workflow","wfc"); + b.ToTable("Workflow", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => @@ -318,6 +306,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("WorkflowId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + + b.Navigation("Workflow"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => @@ -327,6 +317,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("ExecutionPointerId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + + b.Navigation("ExecutionPointer"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Navigation("ExtensionAttributes"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Navigation("ExecutionPointers"); }); #pragma warning restore 612, 618 } diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index fe5c32f81..f352e79c0 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -4,7 +4,7 @@ Workflow Core SQL Server Persistence Provider 1.8.0 Daniel Gerlag - netstandard2.0 + netstandard2.1 WorkflowCore.Persistence.SqlServer WorkflowCore.Persistence.SqlServer workflow;.NET;Core;state machine;WorkflowCore @@ -15,11 +15,11 @@ false false false - 3.1.1 + 3.3.0 Provides support to persist workflows running on Workflow Core to a SQL Server database. - 3.1.1.0 - 3.1.1.0 - 3.1.1 + 3.3.0.0 + 3.3.0.0 + 3.3.0 @@ -28,11 +28,11 @@ - - + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj index 2d2789021..faa1eb934 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj +++ b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj @@ -4,7 +4,7 @@ Workflow Core Sqlite Persistence Provider 1.5.0 Daniel Gerlag - netstandard2.0 + netstandard2.1 WorkflowCore.Persistence.Sqlite WorkflowCore.Persistence.Sqlite workflow;.NET;Core;state machine;WorkflowCore;Sqlite @@ -16,10 +16,10 @@ false false Provides support to persist workflows running on Workflow Core to a Sqlite database. - 3.1.0 - 3.1.0.0 - 3.1.0.0 - 3.1.0 + 3.3.0 + 3.3.0.0 + 3.3.0.0 + 3.3.0 @@ -28,7 +28,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj b/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj index fc4a5d4fd..d211d3d2f 100644 --- a/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj +++ b/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp3.1 WorkflowCore.Sample03 Exe WorkflowCore.Sample03 @@ -16,7 +16,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj index 82107b0e6..96f0355c0 100644 --- a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj +++ b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 WorkflowCore.Sample04 Exe WorkflowCore.Sample04 @@ -25,11 +25,20 @@ - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj index 5ca51a866..2f5937f36 100644 --- a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj +++ b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 true WorkflowCore.Sample07 Exe @@ -26,7 +26,7 @@ - + diff --git a/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj b/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj index dbe49166e..34e1b0433 100644 --- a/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj +++ b/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.2 + netcoreapp3.1 diff --git a/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj b/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj index fef8173cc..974472a25 100644 --- a/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj +++ b/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.2 + netcoreapp3.1 diff --git a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj index 26933096d..766fc8e0c 100644 --- a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj +++ b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp3.0 + netcoreapp3.1 - + diff --git a/test/ScratchPad/ScratchPad.csproj b/test/ScratchPad/ScratchPad.csproj index 4fb61dd24..1ceab6240 100644 --- a/test/ScratchPad/ScratchPad.csproj +++ b/test/ScratchPad/ScratchPad.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + net5.0 ScratchPad Exe ScratchPad diff --git a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj index c58b3243f..2fefbdea8 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj +++ b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj @@ -21,7 +21,7 @@ - + From 2c381556bed3201db0bf4464fb40bd75d743e36e Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 9 Jan 2021 10:43:35 -0800 Subject: [PATCH 078/342] scratchpad project --- test/ScratchPad/ScratchPad.csproj | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/test/ScratchPad/ScratchPad.csproj b/test/ScratchPad/ScratchPad.csproj index 1ceab6240..2b63861b1 100644 --- a/test/ScratchPad/ScratchPad.csproj +++ b/test/ScratchPad/ScratchPad.csproj @@ -1,7 +1,7 @@  - net5.0 + netcoreapp3.1 ScratchPad Exe ScratchPad @@ -10,11 +10,6 @@ false - - - - - From 7a908e89e0bf6a739d68c240803c4a7369f1d14c Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 16 Jan 2021 09:07:39 -0800 Subject: [PATCH 079/342] use message handler instead of session handler --- .../Services/ServiceBusLifeCycleEventHub.cs | 34 +++++++------------ .../WorkflowCore.Providers.Azure.csproj | 6 ++-- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/ServiceBusLifeCycleEventHub.cs b/src/providers/WorkflowCore.Providers.Azure/Services/ServiceBusLifeCycleEventHub.cs index 13ba2df55..85f7a4245 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/ServiceBusLifeCycleEventHub.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/ServiceBusLifeCycleEventHub.cs @@ -16,14 +16,12 @@ public class ServiceBusLifeCycleEventHub : ILifeCycleEventHub private readonly ITopicClient _topicClient; private readonly ILogger _logger; private readonly ISubscriptionClient _subscriptionClient; - private readonly ICollection> _subscribers = - new HashSet>(); - private readonly JsonSerializerSettings _serializerSettings = - new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.All, - ReferenceLoopHandling = ReferenceLoopHandling.Error, - }; + private readonly ICollection> _subscribers = new HashSet>(); + private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.All, + ReferenceLoopHandling = ReferenceLoopHandling.Error, + }; public ServiceBusLifeCycleEventHub( string connectionString, @@ -31,8 +29,7 @@ public ServiceBusLifeCycleEventHub( string subscriptionName, ILoggerFactory logFactory) { - _subscriptionClient = new SubscriptionClient( - connectionString, topicName, subscriptionName); + _subscriptionClient = new SubscriptionClient(connectionString, topicName, subscriptionName); _topicClient = new TopicClient(connectionString, topicName); _logger = logFactory.CreateLogger(GetType()); } @@ -55,14 +52,12 @@ public void Subscribe(Action action) public Task Start() { - var sessionHandlerOptions = new SessionHandlerOptions(ExceptionHandler) + var messageHandlerOptions = new MessageHandlerOptions(ExceptionHandler) { - MaxConcurrentSessions = 1, AutoComplete = false }; - _subscriptionClient.RegisterSessionHandler( - MessageHandler, sessionHandlerOptions); + _subscriptionClient.RegisterMessageHandler(MessageHandler, messageHandlerOptions); return Task.CompletedTask; } @@ -73,10 +68,7 @@ public async Task Stop() await _subscriptionClient.CloseAsync(); } - private async Task MessageHandler( - IMessageSession messageSession, - Message message, - CancellationToken cancellationToken) + private async Task MessageHandler(Message message, CancellationToken cancellationToken) { try { @@ -92,15 +84,13 @@ await _subscriptionClient } catch { - await _subscriptionClient - .AbandonAsync(message.SystemProperties.LockToken); + await _subscriptionClient.AbandonAsync(message.SystemProperties.LockToken); } } private Task ExceptionHandler(ExceptionReceivedEventArgs arg) { - _logger.LogWarning( - default, arg.Exception, "Error on receiving events"); + _logger.LogWarning(default, arg.Exception, "Error on receiving events"); return Task.CompletedTask; } diff --git a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj index 43013c80c..cd09e101e 100644 --- a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj +++ b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj @@ -7,15 +7,15 @@ - Provides distributed lock management on Workflow Core - Provides Queueing support on Workflow Core workflow workflowcore dlm - 3.0.0 + 3.1.0 $(PackageTargetFallback);dnxcore50 https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git Daniel Gerlag - 3.0.0.0 - 3.0.0.0 + 3.1.0.0 + 3.1.0.0 From 6ee54cd4aec33e6aa248f4fe4822319a8f5982af Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 16 Jan 2021 09:17:25 -0800 Subject: [PATCH 080/342] cleanup warnings --- .../SqlLockProvider.cs | 11 ++++------- .../Services/AzureLockManager.cs | 6 ++++-- .../Services/RedisPersistenceProvider.cs | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/providers/WorkflowCore.LockProviders.SqlServer/SqlLockProvider.cs b/src/providers/WorkflowCore.LockProviders.SqlServer/SqlLockProvider.cs index 7726d3ebf..cfeafd36c 100644 --- a/src/providers/WorkflowCore.LockProviders.SqlServer/SqlLockProvider.cs +++ b/src/providers/WorkflowCore.LockProviders.SqlServer/SqlLockProvider.cs @@ -133,12 +133,9 @@ public async Task ReleaseLock(string Id) } } - public async Task Start() - { - } - - public async Task Stop() - { - } + public Task Start() => Task.CompletedTask; + + public Task Stop() => Task.CompletedTask; + } } diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs b/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs index 3d718b6e9..9b6d0bdb1 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs @@ -93,13 +93,15 @@ public async Task Start() _renewTimer = new Timer(RenewLeases, null, RenewInterval, RenewInterval); } - public async Task Stop() + public Task Stop() { if (_renewTimer == null) - return; + return Task.CompletedTask; _renewTimer.Dispose(); _renewTimer = null; + + return Task.CompletedTask; } private async void RenewLeases(object state) diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs index 103e7c442..3e593a550 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs @@ -70,7 +70,7 @@ public async Task> GetRunnableInstances(DateTime asAt) return result; } - public async Task> GetWorkflowInstances(WorkflowStatus? status, string type, DateTime? createdFrom, DateTime? createdTo, int skip, + public Task> GetWorkflowInstances(WorkflowStatus? status, string type, DateTime? createdFrom, DateTime? createdTo, int skip, int take) { throw new NotImplementedException(); From e0500f549c5a658f37a8ecbfa95eb2f9552796ca Mon Sep 17 00:00:00 2001 From: xavier Date: Mon, 25 Jan 2021 16:52:53 +0100 Subject: [PATCH 081/342] Extend RunWorkflowSync Extend RunWorkflowSync using a CancelationToken --- src/WorkflowCore/Interface/ISyncWorkflowRunner.cs | 4 ++++ src/WorkflowCore/Services/SyncWorkflowRunner.cs | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/WorkflowCore/Interface/ISyncWorkflowRunner.cs b/src/WorkflowCore/Interface/ISyncWorkflowRunner.cs index 2fe69771b..051b59e91 100644 --- a/src/WorkflowCore/Interface/ISyncWorkflowRunner.cs +++ b/src/WorkflowCore/Interface/ISyncWorkflowRunner.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; using WorkflowCore.Models; @@ -8,5 +9,8 @@ public interface ISyncWorkflowRunner { Task RunWorkflowSync(string workflowId, int version, TData data, string reference, TimeSpan timeOut, bool persistSate = true) where TData : new(); + + Task RunWorkflowSync(string workflowId, int version, TData data, string reference, CancellationToken token, bool persistSate = true) + where TData : new(); } } \ No newline at end of file diff --git a/src/WorkflowCore/Services/SyncWorkflowRunner.cs b/src/WorkflowCore/Services/SyncWorkflowRunner.cs index 65bf6c626..3655c2fd0 100644 --- a/src/WorkflowCore/Services/SyncWorkflowRunner.cs +++ b/src/WorkflowCore/Services/SyncWorkflowRunner.cs @@ -32,7 +32,15 @@ public SyncWorkflowRunner(IWorkflowHost host, IWorkflowExecutor executor, IDistr _dateTimeProvider = dateTimeProvider; } - public async Task RunWorkflowSync(string workflowId, int version, TData data, string reference, TimeSpan timeOut, bool persistSate = true) + public Task RunWorkflowSync(string workflowId, int version, TData data, + string reference, TimeSpan timeOut, bool persistSate = true) + where TData : new() + { + return RunWorkflowSync(workflowId, version, data, reference, new CancellationTokenSource(timeOut).Token, + persistSate); + } + + public async Task RunWorkflowSync(string workflowId, int version, TData data, string reference, CancellationToken token, bool persistSate = true) where TData : new() { var def = _registry.GetDefinition(workflowId, version); From 868841bb9f484baa3ee6deb0608bb4c3a678fdd5 Mon Sep 17 00:00:00 2001 From: xavier Date: Mon, 25 Jan 2021 16:52:53 +0100 Subject: [PATCH 082/342] Extend RunWorkflowSync Extend RunWorkflowSync using a CancelationToken --- .../Interface/ISyncWorkflowRunner.cs | 4 ++++ src/WorkflowCore/Services/SyncWorkflowRunner.cs | 16 ++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/WorkflowCore/Interface/ISyncWorkflowRunner.cs b/src/WorkflowCore/Interface/ISyncWorkflowRunner.cs index 2fe69771b..051b59e91 100644 --- a/src/WorkflowCore/Interface/ISyncWorkflowRunner.cs +++ b/src/WorkflowCore/Interface/ISyncWorkflowRunner.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; using WorkflowCore.Models; @@ -8,5 +9,8 @@ public interface ISyncWorkflowRunner { Task RunWorkflowSync(string workflowId, int version, TData data, string reference, TimeSpan timeOut, bool persistSate = true) where TData : new(); + + Task RunWorkflowSync(string workflowId, int version, TData data, string reference, CancellationToken token, bool persistSate = true) + where TData : new(); } } \ No newline at end of file diff --git a/src/WorkflowCore/Services/SyncWorkflowRunner.cs b/src/WorkflowCore/Services/SyncWorkflowRunner.cs index 65bf6c626..293c976a0 100644 --- a/src/WorkflowCore/Services/SyncWorkflowRunner.cs +++ b/src/WorkflowCore/Services/SyncWorkflowRunner.cs @@ -32,7 +32,15 @@ public SyncWorkflowRunner(IWorkflowHost host, IWorkflowExecutor executor, IDistr _dateTimeProvider = dateTimeProvider; } - public async Task RunWorkflowSync(string workflowId, int version, TData data, string reference, TimeSpan timeOut, bool persistSate = true) + public Task RunWorkflowSync(string workflowId, int version, TData data, + string reference, TimeSpan timeOut, bool persistSate = true) + where TData : new() + { + return RunWorkflowSync(workflowId, version, data, reference, new CancellationTokenSource(timeOut).Token, + persistSate); + } + + public async Task RunWorkflowSync(string workflowId, int version, TData data, string reference, CancellationToken token, bool persistSate = true) where TData : new() { var def = _registry.GetDefinition(workflowId, version); @@ -63,8 +71,6 @@ public async Task RunWorkflowSync(string workflowId, in wf.ExecutionPointers.Add(_pointerFactory.BuildGenesisPointer(def)); - var stopWatch = new Stopwatch(); - var id = Guid.NewGuid().ToString(); if (persistSate) @@ -81,8 +87,7 @@ public async Task RunWorkflowSync(string workflowId, in try { - stopWatch.Start(); - while ((wf.Status == WorkflowStatus.Runnable) && (timeOut.TotalMilliseconds > stopWatch.ElapsedMilliseconds)) + while ((wf.Status == WorkflowStatus.Runnable) && !token.IsCancellationRequested) { await _executor.Execute(wf); if (persistSate) @@ -91,7 +96,6 @@ public async Task RunWorkflowSync(string workflowId, in } finally { - stopWatch.Stop(); await _lockService.ReleaseLock(id); } From e68d78d4129361ef19920eb135e393318d3ffb60 Mon Sep 17 00:00:00 2001 From: Mike Oldfield Date: Thu, 28 Jan 2021 15:40:37 +0200 Subject: [PATCH 083/342] Refactored DataObjectSerializer to be able to use decimal value type and BsonRepresentation attributes --- .../Services/DataObjectSerializer.cs | 101 ++++++++++++++++-- .../Scenarios/DataIOScenario.cs | 14 ++- .../WorkflowCore.Testing.csproj | 1 + test/WorkflowCore.Testing/WorkflowTest.cs | 8 +- 4 files changed, 112 insertions(+), 12 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs index 894b58ed1..f9d34d004 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs @@ -2,11 +2,9 @@ using MongoDB.Bson.Serialization.Serializers; using MongoDB.Bson; using System; +using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; -using System.Threading.Tasks; -using WorkflowCore.Models; using Newtonsoft.Json; namespace WorkflowCore.Persistence.MongoDB.Services @@ -17,7 +15,7 @@ public class DataObjectSerializer : SerializerBase { TypeNameHandling = TypeNameHandling.Objects, }; - + public override object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { if (context.Reader.CurrentBsonType == BsonType.String) @@ -26,18 +24,103 @@ public override object Deserialize(BsonDeserializationContext context, BsonDeser return JsonConvert.DeserializeObject(raw, SerializerSettings); } - return BsonSerializer.Deserialize(context.Reader, typeof(object)); + var obj = BsonSerializer.Deserialize(context.Reader, typeof(object)); + return obj; } public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) { - var str = JsonConvert.SerializeObject(value, SerializerSettings); - var doc = BsonDocument.Parse(str); - ConvertMetaFormat(doc); + BsonDocument doc; + if (BsonClassMap.IsClassMapRegistered(value.GetType())) + { + doc = value.ToBsonDocument(); + doc.Remove("_t"); + doc.InsertAt(0, new BsonElement("_t", value.GetType().AssemblyQualifiedName)); + AddTypeInformation(doc.Elements, value, string.Empty); + } + else + { + var str = JsonConvert.SerializeObject(value, SerializerSettings); + doc = BsonDocument.Parse(str); + ConvertMetaFormat(doc); + } BsonSerializer.Serialize(context.Writer, doc); } + private void AddTypeInformation(IEnumerable elements, object value, string xPath) + { + foreach (var element in elements) + { + var elementXPath = string.IsNullOrEmpty(xPath) ? element.Name : xPath + "." + element.Name; + if (element.Value.IsBsonDocument) + { + var doc = element.Value.AsBsonDocument; + doc.Remove("_t"); + doc.InsertAt(0, new BsonElement("_t", GetTypeNameFromXPath(value, elementXPath))); + AddTypeInformation(doc.Elements, value, elementXPath); + } + if (element.Value.IsBsonArray) + { + AddTypeInformation(element.Value.AsBsonArray, value, elementXPath); + } + } + } + + private string GetTypeNameFromXPath(object root, string xPath) + { + var parts = xPath.Split('.').ToList(); + object value = root; + while (parts.Count > 0) + { + var subPath = parts[0]; + if (subPath[0] == '[') + { + var index = Int32.Parse(subPath.Trim('[', ']')); + if (value.GetType().IsSubclassOf(typeof(IList)) || value.GetType().IsArray) + { + IList list = (IList) value; + value = list[index]; + } + else + { + throw new NotSupportedException(); + } + } + else + { + var propInfo = value.GetType().GetProperty(subPath); + value = propInfo.GetValue(value); + } + + parts.RemoveAt(0); + } + + return value.GetType().AssemblyQualifiedName; + } + + private void AddTypeInformation(IEnumerable elements, object value, string xPath) + { + //foreach (var element in elements) + for (int i = 0; i < elements.Count(); i++) + { + var element = elements.ElementAt(i); + if (element.IsBsonDocument) + { + var doc = element.AsBsonDocument; + var elementXPath = xPath + $".[{i}]"; + doc.Remove("_t"); + doc.InsertAt(0, new BsonElement("_t", GetTypeNameFromXPath(value, elementXPath))); + AddTypeInformation(doc.Elements, value, elementXPath); + } + + if (element.IsBsonArray) + { + AddTypeInformation(element.AsBsonArray, value, xPath); + } + } + } + private static void ConvertMetaFormat(BsonDocument root) { var stack = new Stack(); @@ -72,4 +155,4 @@ private static void ConvertMetaFormat(BsonDocument root) } } } -} +} \ No newline at end of file diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs index 630bcbfe7..0e460defd 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs @@ -29,6 +29,14 @@ public class MyDataClass public int Value1 { get; set; } public int Value2 { get; set; } public int Value3 { get; set; } + public decimal Value4 { get; set; } + + public DataSubclass SubValue { get; set; } + } + + public class DataSubclass + { + public decimal Value5 { get; set; } } public class DataIOWorkflow : IWorkflow @@ -47,18 +55,20 @@ public void Build(IWorkflowBuilder builder) public DataIOScenario() { - Setup(); + Setup(true); } [Fact] public void Scenario() { - var workflowId = StartWorkflow(new MyDataClass() { Value1 = 2, Value2 = 3 }); + decimal v4 = 1.235465673450897890m; + var workflowId = StartWorkflow(new MyDataClass() {Value1 = 2, Value2 = 3, Value4 = v4, SubValue = new DataSubclass() {Value5 = v4}}); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); UnhandledStepErrors.Count.Should().Be(0); GetData(workflowId).Value3.Should().Be(5); + GetData(workflowId).Value4.Should().Be(v4); } } } diff --git a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj index 32f9c1363..fd6508887 100644 --- a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj +++ b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj @@ -12,6 +12,7 @@ + diff --git a/test/WorkflowCore.Testing/WorkflowTest.cs b/test/WorkflowCore.Testing/WorkflowTest.cs index f61d6be0a..32a1259be 100644 --- a/test/WorkflowCore.Testing/WorkflowTest.cs +++ b/test/WorkflowCore.Testing/WorkflowTest.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using MongoDB.Bson.Serialization; using WorkflowCore.Interface; using WorkflowCore.Models; @@ -20,7 +21,7 @@ public abstract class WorkflowTest : IDisposable protected IPersistenceProvider PersistenceProvider; protected List UnhandledStepErrors = new List(); - protected virtual void Setup() + protected virtual void Setup(bool registerClassMap = false) { //setup dependency injection IServiceCollection services = new ServiceCollection(); @@ -33,6 +34,11 @@ protected virtual void Setup() var loggerFactory = serviceProvider.GetService(); //loggerFactory.AddConsole(LogLevel.Debug); + if (registerClassMap && !BsonClassMap.IsClassMapRegistered(typeof(TData))) + { + BsonClassMap.RegisterClassMap(map => map.AutoMap()); + } + PersistenceProvider = serviceProvider.GetService(); Host = serviceProvider.GetService(); Host.RegisterWorkflow(); From d0f233b9da59d7bc04a3f525f1c88da498c2aeae Mon Sep 17 00:00:00 2001 From: Mike Oldfield Date: Thu, 28 Jan 2021 15:53:53 +0200 Subject: [PATCH 084/342] Fixed build issue --- src/samples/WorkflowCore.TestSample01/NUnitTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/samples/WorkflowCore.TestSample01/NUnitTest.cs b/src/samples/WorkflowCore.TestSample01/NUnitTest.cs index 8c83661d8..cec26fe9e 100644 --- a/src/samples/WorkflowCore.TestSample01/NUnitTest.cs +++ b/src/samples/WorkflowCore.TestSample01/NUnitTest.cs @@ -13,9 +13,9 @@ namespace WorkflowCore.TestSample01 public class NUnitTest : WorkflowTest { [SetUp] - protected override void Setup() + protected override void Setup(bool registerClassMap = false) { - base.Setup(); + base.Setup(registerClassMap); } [Test] From 9a04d1c748cc53c2aa206c8e355badfdbf6fcec0 Mon Sep 17 00:00:00 2001 From: Mike Oldfield Date: Fri, 29 Jan 2021 17:27:13 +0200 Subject: [PATCH 085/342] Fixed generic lists serialization problem --- .../Services/DataObjectSerializer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs index f9d34d004..2cf6cab3e 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs @@ -77,7 +77,7 @@ private string GetTypeNameFromXPath(object root, string xPath) if (subPath[0] == '[') { var index = Int32.Parse(subPath.Trim('[', ']')); - if (value.GetType().IsSubclassOf(typeof(IList)) || value.GetType().IsArray) + if ((value is IList) || value.GetType().IsArray) { IList list = (IList) value; value = list[index]; From b4fa2f6c5039613c702330005649476628cb9018 Mon Sep 17 00:00:00 2001 From: Mikhail Merkulov Date: Sat, 6 Feb 2021 21:11:09 +0200 Subject: [PATCH 086/342] Mongodb documentation updated with details on object serialization --- .../README.md | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/README.md b/src/providers/WorkflowCore.Persistence.MongoDB/README.md index 5dacb7c6c..911d8a9e4 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/README.md +++ b/src/providers/WorkflowCore.Persistence.MongoDB/README.md @@ -17,3 +17,35 @@ Use the .UseMongoDB extension method when building your service provider. ```C# services.AddWorkflow(x => x.UseMongoDB(@"mongodb://localhost:27017", "workflow")); ``` + +### State object serialization + +By default (to maintain backwards compatibility), the state object is serialized using a two step serialization process using object -> JSON -> BSON serialization. +This approach has some limitations, for example you cannot control which types will be used in MongoDB for particular fields and you cannot use basic types that are not present in JSON (decimal, timestamp, etc). + +To eliminate these limitations, you can use a direct object -> BSON serialization and utilize all serialization possibilities that MongoDb driver provides. You can read more in the [MongoDb CSharp documentation](https://mongodb.github.io/mongo-csharp-driver/1.11/serialization/). +To enable direct serilization you need to register a class map for you state class somewhere in your startup process before you run `WorkflowHost`. + +```C# +private void RunWorkflow() +{ + var host = this._serviceProvider.GetService(); + if (host == null) + { + return; + } + + if (!BsonClassMap.IsClassMapRegistered(typeof(MyWorkflowState))) + { + BsonClassMap.RegisterClassMap(cm => + { + cm.AutoMap(); + }); + } + + host.RegisterWorkflow(); + + host.Start(); +} + +``` From d7ac340e6d0522ce3e42f89d3c8b23ee42d249b0 Mon Sep 17 00:00:00 2001 From: Mikhail Merkulov Date: Sat, 6 Feb 2021 21:11:23 +0200 Subject: [PATCH 087/342] Version bump --- src/WorkflowCore/WorkflowCore.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 2f465db0d..2ef5a4a1c 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.3.5 - 3.3.5.0 - 3.3.5.0 + 3.3.6 + 3.3.6.0 + 3.3.6.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.3.5 + 3.3.6 From 11368e8e0cbd4940648066d8016c573cb69ad9da Mon Sep 17 00:00:00 2001 From: Mikhail Merkulov Date: Tue, 9 Feb 2021 19:31:28 +0200 Subject: [PATCH 088/342] Rollback 3.3.6 -> 3.3.5 --- src/WorkflowCore/WorkflowCore.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 2ef5a4a1c..2f465db0d 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.3.6 - 3.3.6.0 - 3.3.6.0 + 3.3.5 + 3.3.5.0 + 3.3.5.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.3.6 + 3.3.5 From 96e5e66a4eac479749be4a53e8853426689e67d4 Mon Sep 17 00:00:00 2001 From: Mikhail Merkulov Date: Tue, 9 Feb 2021 19:32:21 +0200 Subject: [PATCH 089/342] Version bump --- .../WorkflowCore.Persistence.MongoDB.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj index b6e6204c0..b365d33f6 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj +++ b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj @@ -14,11 +14,11 @@ false false false - 3.0.3 + 3.0.4 Provides support to persist workflows running on Workflow Core to a MongoDB database. - 3.0.3.0 - 3.0.3.0 - 3.0.3 + 3.0.4.0 + 3.0.4.0 + 3.0.4 From cedc15176d0bd195980bc5f1c6dfe0ff4e001aca Mon Sep 17 00:00:00 2001 From: glucaci Date: Sun, 14 Feb 2021 11:48:00 +0100 Subject: [PATCH 090/342] Execute post middleware in any case --- src/WorkflowCore/Services/WorkflowExecutor.cs | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index c6241fd64..0bdf8ce36 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -212,7 +212,10 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo workflow.NextExecution = null; if (workflow.Status == WorkflowStatus.Complete) + { + await RunPostMiddleware(workflow, def); return; + } foreach (var pointer in workflow.ExecutionPointers.Where(x => x.Active && (x.Children ?? new List()).Count == 0)) { @@ -242,18 +245,17 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo } if ((workflow.NextExecution != null) || (workflow.ExecutionPointers.Any(x => x.EndTime == null))) + { + await RunPostMiddleware(workflow, def); return; + } workflow.Status = WorkflowStatus.Complete; workflow.CompleteTime = _datetimeProvider.UtcNow; - using (var scope = _serviceProvider.CreateScope()) - { - var middlewareRunner = scope.ServiceProvider.GetRequiredService(); - await middlewareRunner.RunPostMiddleware(workflow, def); - } + await RunPostMiddleware(workflow, def); - _publisher.PublishNotification(new WorkflowCompleted() + _publisher.PublishNotification(new WorkflowCompleted { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, @@ -262,5 +264,14 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo Version = workflow.Version }); } + + private Task RunPostMiddleware(WorkflowInstance workflow, WorkflowDefinition def) + { + using (var scope = _serviceProvider.CreateScope()) + { + var middlewareRunner = scope.ServiceProvider.GetRequiredService(); + return middlewareRunner.RunPostMiddleware(workflow, def); + } + } } } From f462d6e4f815f2e879c6cb78178f090a49baf4e9 Mon Sep 17 00:00:00 2001 From: glucaci Date: Sun, 14 Feb 2021 11:59:15 +0100 Subject: [PATCH 091/342] Add post middleware in more places --- src/WorkflowCore/Services/WorkflowExecutor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index 0bdf8ce36..01ce4c924 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -222,6 +222,7 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo if (!pointer.SleepUntil.HasValue) { workflow.NextExecution = 0; + await RunPostMiddleware(workflow, def); return; } @@ -237,6 +238,7 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo if (!pointer.SleepUntil.HasValue) { workflow.NextExecution = 0; + await RunPostMiddleware(workflow, def); return; } From 55db92852cf1b3f8b1f20d24831ab911ef84cc3b Mon Sep 17 00:00:00 2001 From: glucaci Date: Sun, 14 Feb 2021 12:57:58 +0100 Subject: [PATCH 092/342] Fix workflow status mongo serialization --- .../Services/MongoPersistenceProvider.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index 40d4e5409..041b9ae96 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using MongoDB.Bson; using MongoDB.Bson.Serialization.Conventions; +using MongoDB.Bson.Serialization.Serializers; using MongoDB.Driver.Linq; using WorkflowCore.Interface; using WorkflowCore.Models; @@ -44,7 +45,8 @@ static MongoPersistenceProvider() x.MapProperty(y => y.WorkflowDefinitionId); x.MapProperty(y => y.Version); x.MapProperty(y => y.NextExecution); - x.MapProperty(y => y.Status); + x.MapProperty(y => y.Status) + .SetSerializer(new EnumSerializer(BsonType.String)); x.MapProperty(y => y.CreateTime); x.MapProperty(y => y.CompleteTime); x.MapProperty(y => y.ExecutionPointers); From e15b2a6afcfb587908e240975cf9120c513573dc Mon Sep 17 00:00:00 2001 From: glucaci Date: Mon, 15 Feb 2021 08:00:05 +0100 Subject: [PATCH 093/342] Cleanup --- src/WorkflowCore/Services/WorkflowExecutor.cs | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index 01ce4c924..ee58e32bb 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -96,7 +96,13 @@ public async Task Execute(WorkflowInstance workflow, Can _cancellationProcessor.ProcessCancellations(workflow, def, wfResult); } ProcessAfterExecutionIteration(workflow, def, wfResult); - await DetermineNextExecutionTime(workflow, def); + DetermineNextExecutionTime(workflow, def); + + using (var scope = _serviceProvider.CreateScope()) + { + var middlewareRunner = scope.ServiceProvider.GetRequiredService(); + await middlewareRunner.RunPostMiddleware(workflow, def); + } return wfResult; } @@ -206,14 +212,13 @@ private void ProcessAfterExecutionIteration(WorkflowInstance workflow, WorkflowD } } - private async Task DetermineNextExecutionTime(WorkflowInstance workflow, WorkflowDefinition def) + private void DetermineNextExecutionTime(WorkflowInstance workflow, WorkflowDefinition def) { //TODO: move to own class workflow.NextExecution = null; if (workflow.Status == WorkflowStatus.Complete) { - await RunPostMiddleware(workflow, def); return; } @@ -222,7 +227,6 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo if (!pointer.SleepUntil.HasValue) { workflow.NextExecution = 0; - await RunPostMiddleware(workflow, def); return; } @@ -238,7 +242,6 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo if (!pointer.SleepUntil.HasValue) { workflow.NextExecution = 0; - await RunPostMiddleware(workflow, def); return; } @@ -248,15 +251,12 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo if ((workflow.NextExecution != null) || (workflow.ExecutionPointers.Any(x => x.EndTime == null))) { - await RunPostMiddleware(workflow, def); return; } workflow.Status = WorkflowStatus.Complete; workflow.CompleteTime = _datetimeProvider.UtcNow; - await RunPostMiddleware(workflow, def); - _publisher.PublishNotification(new WorkflowCompleted { EventTimeUtc = _datetimeProvider.UtcNow, @@ -266,14 +266,5 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo Version = workflow.Version }); } - - private Task RunPostMiddleware(WorkflowInstance workflow, WorkflowDefinition def) - { - using (var scope = _serviceProvider.CreateScope()) - { - var middlewareRunner = scope.ServiceProvider.GetRequiredService(); - return middlewareRunner.RunPostMiddleware(workflow, def); - } - } } } From 200f16fff9ab53fb1f3b5705eaaa1bef1ab44aa3 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 16 Feb 2021 08:14:45 -0800 Subject: [PATCH 094/342] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 20 ++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..471baed24 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,20 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..bbcbbe7d6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From d0f3f90c23144bed4d0cb4b09008d7d36e8246f9 Mon Sep 17 00:00:00 2001 From: John Demetriou Date: Thu, 18 Feb 2021 11:14:59 +0200 Subject: [PATCH 095/342] Removed TODO. It's clear Item3 is definition --- src/WorkflowCore/Services/WorkflowRegistry.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/WorkflowCore/Services/WorkflowRegistry.cs b/src/WorkflowCore/Services/WorkflowRegistry.cs index c09189a1c..22f0ba608 100644 --- a/src/WorkflowCore/Services/WorkflowRegistry.cs +++ b/src/WorkflowCore/Services/WorkflowRegistry.cs @@ -23,7 +23,6 @@ public WorkflowDefinition GetDefinition(string workflowId, int? version = null) if (version.HasValue) { var entry = _registry.FirstOrDefault(x => x.Item1 == workflowId && x.Item2 == version.Value); - // TODO: What in the heck does Item3 mean? return entry?.Item3; } else From 8361a0f5ed76ab52581b6fc36567d8e6bc522865 Mon Sep 17 00:00:00 2001 From: John Demetriou Date: Thu, 18 Feb 2021 11:15:35 +0200 Subject: [PATCH 096/342] Switched to named ValueTuples to improve code readability --- src/WorkflowCore/Services/WorkflowRegistry.cs | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/WorkflowCore/Services/WorkflowRegistry.cs b/src/WorkflowCore/Services/WorkflowRegistry.cs index 22f0ba608..df4619621 100644 --- a/src/WorkflowCore/Services/WorkflowRegistry.cs +++ b/src/WorkflowCore/Services/WorkflowRegistry.cs @@ -11,7 +11,7 @@ namespace WorkflowCore.Services public class WorkflowRegistry : IWorkflowRegistry { private readonly IServiceProvider _serviceProvider; - private readonly BlockingCollection> _registry = new BlockingCollection>(); + private readonly BlockingCollection<(string, int, WorkflowDefinition)> _registry = new BlockingCollection<(string, int, WorkflowDefinition)>(); public WorkflowRegistry(IServiceProvider serviceProvider) { @@ -20,23 +20,24 @@ public WorkflowRegistry(IServiceProvider serviceProvider) public WorkflowDefinition GetDefinition(string workflowId, int? version = null) { + (string workflowId, int version, WorkflowDefinition definition) workflowEntry; if (version.HasValue) { - var entry = _registry.FirstOrDefault(x => x.Item1 == workflowId && x.Item2 == version.Value); - return entry?.Item3; + workflowEntry = _registry.FirstOrDefault(x => x.Item1 == workflowId && x.Item2 == version.Value); } else { - var entry = _registry.Where(x => x.Item1 == workflowId).OrderByDescending(x => x.Item2) - .FirstOrDefault(); - return entry?.Item3; + workflowEntry = _registry.Where(x => x.Item1 == workflowId).OrderByDescending(x => x.Item2) + .FirstOrDefault(); } + + return workflowEntry != default ? workflowEntry.definition : default; } public void DeregisterWorkflow(string workflowId, int version) { var definition = _registry.FirstOrDefault(x => x.Item1 == workflowId && x.Item2 == version); - if (definition != null) + if (definition != default) { _registry.TryTake(out definition); } @@ -49,10 +50,10 @@ public void RegisterWorkflow(IWorkflow workflow) throw new InvalidOperationException($"Workflow {workflow.Id} version {workflow.Version} is already registered"); } - var builder = _serviceProvider.GetService().UseData(); + var builder = _serviceProvider.GetService().UseData(); workflow.Build(builder); var def = builder.Build(workflow.Id, workflow.Version); - _registry.Add(Tuple.Create(workflow.Id, workflow.Version, def)); + _registry.Add((workflow.Id, workflow.Version, def)); } public void RegisterWorkflow(WorkflowDefinition definition) @@ -62,7 +63,7 @@ public void RegisterWorkflow(WorkflowDefinition definition) throw new InvalidOperationException($"Workflow {definition.Id} version {definition.Version} is already registered"); } - _registry.Add(Tuple.Create(definition.Id, definition.Version, definition)); + _registry.Add((definition.Id, definition.Version, definition)); } public void RegisterWorkflow(IWorkflow workflow) @@ -76,13 +77,13 @@ public void RegisterWorkflow(IWorkflow workflow) var builder = _serviceProvider.GetService().UseData(); workflow.Build(builder); var def = builder.Build(workflow.Id, workflow.Version); - _registry.Add(Tuple.Create(workflow.Id, workflow.Version, def)); + _registry.Add((workflow.Id, workflow.Version, def)); } public bool IsRegistered(string workflowId, int version) { var definition = _registry.FirstOrDefault(x => x.Item1 == workflowId && x.Item2 == version); - return (definition != null); + return definition != default; } public IEnumerable GetAllDefinitions() @@ -90,4 +91,4 @@ public IEnumerable GetAllDefinitions() return _registry.Select(i => i.Item3); } } -} +} \ No newline at end of file From 653fa003080ffebeb33be150e5d7524904265fc5 Mon Sep 17 00:00:00 2001 From: john Date: Sun, 21 Feb 2021 10:10:48 +0200 Subject: [PATCH 097/342] Switched to named tuple --- src/WorkflowCore/Services/WorkflowRegistry.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WorkflowCore/Services/WorkflowRegistry.cs b/src/WorkflowCore/Services/WorkflowRegistry.cs index df4619621..66a310ec0 100644 --- a/src/WorkflowCore/Services/WorkflowRegistry.cs +++ b/src/WorkflowCore/Services/WorkflowRegistry.cs @@ -11,7 +11,7 @@ namespace WorkflowCore.Services public class WorkflowRegistry : IWorkflowRegistry { private readonly IServiceProvider _serviceProvider; - private readonly BlockingCollection<(string, int, WorkflowDefinition)> _registry = new BlockingCollection<(string, int, WorkflowDefinition)>(); + private readonly BlockingCollection<(string workfloId, int version, WorkflowDefinition definition)> _registry = new BlockingCollection<(string, int, WorkflowDefinition)>(); public WorkflowRegistry(IServiceProvider serviceProvider) { From 141f70407bf8d5eaeeec7d4081b5afaf4afb6d97 Mon Sep 17 00:00:00 2001 From: DevsAnon Date: Tue, 23 Feb 2021 09:17:05 +0200 Subject: [PATCH 098/342] Use ValueTuple named values everywhere in WorkflowRegistry --- src/WorkflowCore/Services/WorkflowRegistry.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/WorkflowCore/Services/WorkflowRegistry.cs b/src/WorkflowCore/Services/WorkflowRegistry.cs index 66a310ec0..01d0625a5 100644 --- a/src/WorkflowCore/Services/WorkflowRegistry.cs +++ b/src/WorkflowCore/Services/WorkflowRegistry.cs @@ -11,7 +11,7 @@ namespace WorkflowCore.Services public class WorkflowRegistry : IWorkflowRegistry { private readonly IServiceProvider _serviceProvider; - private readonly BlockingCollection<(string workfloId, int version, WorkflowDefinition definition)> _registry = new BlockingCollection<(string, int, WorkflowDefinition)>(); + private readonly BlockingCollection<(string workflowId, int version, WorkflowDefinition definition)> _registry = new BlockingCollection<(string, int, WorkflowDefinition)>(); public WorkflowRegistry(IServiceProvider serviceProvider) { @@ -23,11 +23,11 @@ public WorkflowDefinition GetDefinition(string workflowId, int? version = null) (string workflowId, int version, WorkflowDefinition definition) workflowEntry; if (version.HasValue) { - workflowEntry = _registry.FirstOrDefault(x => x.Item1 == workflowId && x.Item2 == version.Value); + workflowEntry = _registry.FirstOrDefault(x => x.workflowId == workflowId && x.version == version.Value); } else { - workflowEntry = _registry.Where(x => x.Item1 == workflowId).OrderByDescending(x => x.Item2) + workflowEntry = _registry.Where(x => x.workflowId == workflowId).OrderByDescending(x => x.version) .FirstOrDefault(); } @@ -36,7 +36,7 @@ public WorkflowDefinition GetDefinition(string workflowId, int? version = null) public void DeregisterWorkflow(string workflowId, int version) { - var definition = _registry.FirstOrDefault(x => x.Item1 == workflowId && x.Item2 == version); + var definition = _registry.FirstOrDefault(x => x.workflowId == workflowId && x.version == version); if (definition != default) { _registry.TryTake(out definition); @@ -45,7 +45,7 @@ public void DeregisterWorkflow(string workflowId, int version) public void RegisterWorkflow(IWorkflow workflow) { - if (_registry.Any(x => x.Item1 == workflow.Id && x.Item2 == workflow.Version)) + if (_registry.Any(x => x.workflowId == workflow.Id && x.version == workflow.Version)) { throw new InvalidOperationException($"Workflow {workflow.Id} version {workflow.Version} is already registered"); } @@ -58,7 +58,7 @@ public void RegisterWorkflow(IWorkflow workflow) public void RegisterWorkflow(WorkflowDefinition definition) { - if (_registry.Any(x => x.Item1 == definition.Id && x.Item2 == definition.Version)) + if (_registry.Any(x => x.workflowId == definition.Id && x.version == definition.Version)) { throw new InvalidOperationException($"Workflow {definition.Id} version {definition.Version} is already registered"); } @@ -69,7 +69,7 @@ public void RegisterWorkflow(WorkflowDefinition definition) public void RegisterWorkflow(IWorkflow workflow) where TData : new() { - if (_registry.Any(x => x.Item1 == workflow.Id && x.Item2 == workflow.Version)) + if (_registry.Any(x => x.workflowId == workflow.Id && x.version == workflow.Version)) { throw new InvalidOperationException($"Workflow {workflow.Id} version {workflow.Version} is already registered"); } @@ -82,13 +82,13 @@ public void RegisterWorkflow(IWorkflow workflow) public bool IsRegistered(string workflowId, int version) { - var definition = _registry.FirstOrDefault(x => x.Item1 == workflowId && x.Item2 == version); + var definition = _registry.FirstOrDefault(x => x.workflowId == workflowId && x.version == version); return definition != default; } public IEnumerable GetAllDefinitions() { - return _registry.Select(i => i.Item3); + return _registry.Select(i => i.definition); } } } \ No newline at end of file From dbc5af37797e2d38f23d3b91a7c3f32eefdd4915 Mon Sep 17 00:00:00 2001 From: rapmue Date: Wed, 24 Feb 2021 09:28:53 +0100 Subject: [PATCH 099/342] Fixed wrong JSON and YAML definitions It was unclear in the JSON and YAML definitions what the related properties of the step and the DTO are. Hopefully I understood it correctly. --- docs/getting-started.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 49ac1f38e..26bc01879 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -142,7 +142,7 @@ public class MyDataClass { public int Value1 { get; set; } public int Value2 { get; set; } - public int Value3 { get; set; } + public int Answer { get; set; } } //Our workflow definition with strongly typed internal data and mapped inputs & outputs @@ -154,9 +154,9 @@ public class PassingDataWorkflow : IWorkflow .StartWith() .Input(step => step.Input1, data => data.Value1) .Input(step => step.Input2, data => data.Value2) - .Output(data => data.Value3, step => step.Output) + .Output(data => data.Answer, step => step.Output) .Then() - .Input(step => step.Message, data => "The answer is " + data.Value3.ToString()); + .Input(step => step.Message, data => "The answer is " + data.Answer.ToString()); } ... } @@ -175,8 +175,8 @@ or in jSON format "StepType": "MyApp.AddNumbers, MyApp", "NextStepId": "ShowResult", "Inputs": { - "Value1": "data.Value1", - "Value2": "data.Value2" + "Input1": "data.Value1", + "Input2": "data.Value2" }, "Outputs": { "Answer": "step.Output" @@ -186,7 +186,7 @@ or in jSON format "Id": "ShowResult", "StepType": "MyApp.CustomMessage, MyApp", "Inputs": { - "Message": "\"The answer is \" + data.Value1" + "Message": "\"The answer is \" + data.Answer" } } ] @@ -203,14 +203,14 @@ Steps: StepType: MyApp.AddNumbers, MyApp NextStepId: ShowResult Inputs: - Value1: data.Value1 - Value2: data.Value2 + Input1: data.Value1 + Input2: data.Value2 Outputs: Answer: step.Output - Id: ShowResult StepType: MyApp.CustomMessage, MyApp Inputs: - Message: '"The answer is " + data.Value1' + Message: '"The answer is " + data.Answer' ``` From 3ca050f2cb0d6603b374e63e700313ed0711917e Mon Sep 17 00:00:00 2001 From: macrian Date: Thu, 11 Mar 2021 10:34:50 +0200 Subject: [PATCH 100/342] Remove unnecessary parenthesis from everywhere --- .../Services/DefinitionLoader.cs | 2 +- src/WorkflowCore/Models/ExecutionResult.cs | 14 ++-- .../Models/Search/SearchFilter.cs | 30 ++++---- src/WorkflowCore/Models/StepBody.cs | 6 +- src/WorkflowCore/Primitives/Foreach.cs | 4 +- src/WorkflowCore/Primitives/If.cs | 2 +- src/WorkflowCore/Primitives/OutcomeSwitch.cs | 2 +- src/WorkflowCore/Primitives/Recur.cs | 4 +- src/WorkflowCore/Primitives/Schedule.cs | 4 +- src/WorkflowCore/Primitives/Sequence.cs | 2 +- src/WorkflowCore/Primitives/When.cs | 2 +- src/WorkflowCore/Primitives/While.cs | 2 +- .../Services/ActivityController.cs | 8 +-- .../Services/BackgroundTasks/EventConsumer.cs | 2 +- .../SingleNodeQueueProvider.cs | 2 +- .../Services/ErrorHandlers/SuspendHandler.cs | 2 +- .../ErrorHandlers/TerminateHandler.cs | 2 +- .../Services/ExecutionPointerFactory.cs | 6 +- .../Services/ExecutionResultProcessor.cs | 6 +- .../Services/FluentBuilders/StepBuilder.cs | 40 +++++------ .../Services/WorkflowController.cs | 8 +-- src/WorkflowCore/Services/WorkflowExecutor.cs | 12 ++-- .../Models/UserStepContainer.cs | 2 +- .../WorkflowCore.Users/Primitives/UserTask.cs | 4 +- .../StepBuilderExtensions.cs | 4 +- .../WorkflowHostExtensions.cs | 2 +- .../WorkflowInstanceExtensions.cs | 2 +- .../Services/UserTaskBuilder.cs | 2 +- .../ExtensionMethods.cs | 2 +- .../Services/DataObjectSerializer.cs | 2 +- .../ModelExtensions.cs | 28 ++++---- .../Services/DynamoDbProvisioner.cs | 56 +++++++-------- .../Services/DynamoLockProvider.cs | 14 ++-- .../Services/DynamoPersistenceProvider.cs | 70 +++++++++---------- .../Services/KinesisProvider.cs | 8 +-- .../Services/KinesisStreamConsumer.cs | 12 ++-- .../Services/KinesisTracker.cs | 14 ++-- .../Models/PersistedEvent.cs | 6 +- .../Models/PersistedSubscription.cs | 6 +- .../Models/PersistedWorkflow.cs | 6 +- .../Services/CosmosDbProvisioner.cs | 4 +- .../Models/WorkflowSearchModel.cs | 8 +-- .../Services/RedisLifeCycleEventHub.cs | 2 +- .../Services/RedisLockProvider.cs | 2 +- .../Services/RedisPersistenceProvider.cs | 2 +- .../Services/RedisQueueProvider.cs | 2 +- .../Services/RabbitMQProvider.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../Services/QueueConfigProvider.cs | 2 +- .../WorkflowCore.Sample09/ForEachWorkflow.cs | 2 +- .../ForEachSyncWorkflow.cs | 2 +- src/samples/WorkflowCore.Sample10/Program.cs | 2 +- src/samples/WorkflowCore.Sample11/Program.cs | 2 +- src/samples/WorkflowCore.Sample12/Program.cs | 2 +- src/samples/WorkflowCore.Sample18/Program.cs | 2 +- .../WorkflowCore.TestSample01/NUnitTest.cs | 2 +- .../WorkflowCore.TestSample01/xUnitTest.cs | 2 +- test/Docker.Testify/DockerSetup.cs | 6 +- test/ScratchPad/ElasticTest.cs | 4 +- test/ScratchPad/Program.cs | 2 +- .../Scenarios/ActivityScenario.cs | 4 +- .../Scenarios/CompensationScenario.cs | 4 +- .../Scenarios/CompensationScenario2.cs | 4 +- .../Scenarios/DataIOScenario.cs | 2 +- .../Scenarios/DecisionScenario.cs | 4 +- .../Scenarios/DynamicDataIOScenario.cs | 2 +- .../Scenarios/EventScenario.cs | 2 +- .../Scenarios/ForeachScenario.cs | 2 +- .../Scenarios/ForeachSyncScenario.cs | 2 +- .../Scenarios/IfScenario.cs | 2 +- .../Scenarios/SagaScenario.cs | 4 +- .../Scenarios/StoredJsonScenario.cs | 4 +- .../Scenarios/StoredYamlScenario.cs | 2 +- .../Scenarios/WhenScenario.cs | 2 +- .../Scenarios/WhileScenario.cs | 2 +- .../SearchIndexTests.cs | 16 ++--- test/WorkflowCore.TestAssets/Utils.cs | 2 +- test/WorkflowCore.Testing/JsonWorkflowTest.cs | 2 +- test/WorkflowCore.Testing/WorkflowTest.cs | 2 +- test/WorkflowCore.Testing/YamlWorkflowTest.cs | 2 +- .../BasePersistenceFixture.cs | 54 +++++++------- .../Models/MemberMapParameterTests.cs | 8 +-- .../ExecutionResultProcessorFixture.cs | 36 +++++----- .../Services/WorkflowExecutorFixture.cs | 44 ++++++------ 84 files changed, 332 insertions(+), 332 deletions(-) diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index db92d5430..d408bfc07 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -250,7 +250,7 @@ private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, Wo private void AttachOutcomes(StepSourceV1 source, Type dataType, WorkflowStep step) { if (!string.IsNullOrEmpty(source.NextStepId)) - step.Outcomes.Add(new ValueOutcome() { ExternalNextStepId = $"{source.NextStepId}" }); + step.Outcomes.Add(new ValueOutcome { ExternalNextStepId = $"{source.NextStepId}" }); var dataParameter = Expression.Parameter(dataType, "data"); var outcomeParameter = Expression.Parameter(typeof(object), "outcome"); diff --git a/src/WorkflowCore/Models/ExecutionResult.cs b/src/WorkflowCore/Models/ExecutionResult.cs index 54c2c55f2..14c562802 100644 --- a/src/WorkflowCore/Models/ExecutionResult.cs +++ b/src/WorkflowCore/Models/ExecutionResult.cs @@ -35,7 +35,7 @@ public ExecutionResult(object outcome) public static ExecutionResult Outcome(object value) { - return new ExecutionResult() + return new ExecutionResult { Proceed = true, OutcomeValue = value @@ -44,7 +44,7 @@ public static ExecutionResult Outcome(object value) public static ExecutionResult Next() { - return new ExecutionResult() + return new ExecutionResult { Proceed = true, OutcomeValue = null @@ -53,7 +53,7 @@ public static ExecutionResult Next() public static ExecutionResult Persist(object persistenceData) { - return new ExecutionResult() + return new ExecutionResult { Proceed = false, PersistenceData = persistenceData @@ -62,7 +62,7 @@ public static ExecutionResult Persist(object persistenceData) public static ExecutionResult Branch(List branches, object persistenceData) { - return new ExecutionResult() + return new ExecutionResult { Proceed = false, PersistenceData = persistenceData, @@ -72,7 +72,7 @@ public static ExecutionResult Branch(List branches, object persistenceDa public static ExecutionResult Sleep(TimeSpan duration, object persistenceData) { - return new ExecutionResult() + return new ExecutionResult { Proceed = false, SleepFor = duration, @@ -82,7 +82,7 @@ public static ExecutionResult Sleep(TimeSpan duration, object persistenceData) public static ExecutionResult WaitForEvent(string eventName, string eventKey, DateTime effectiveDate) { - return new ExecutionResult() + return new ExecutionResult { Proceed = false, EventName = eventName, @@ -93,7 +93,7 @@ public static ExecutionResult WaitForEvent(string eventName, string eventKey, Da public static ExecutionResult WaitForActivity(string activityName, object subscriptionData, DateTime effectiveDate) { - return new ExecutionResult() + return new ExecutionResult { Proceed = false, EventName = Event.EventTypeActivity, diff --git a/src/WorkflowCore/Models/Search/SearchFilter.cs b/src/WorkflowCore/Models/Search/SearchFilter.cs index fd7d8c7a4..b4d7ff66b 100644 --- a/src/WorkflowCore/Models/Search/SearchFilter.cs +++ b/src/WorkflowCore/Models/Search/SearchFilter.cs @@ -21,13 +21,13 @@ public class ScalarFilter : SearchFilter { public object Value { get; set; } - public static SearchFilter Equals(Expression> property, object value) => new ScalarFilter() + public static SearchFilter Equals(Expression> property, object value) => new ScalarFilter { Property = property, Value = value }; - public static SearchFilter Equals(Expression> property, object value) => new ScalarFilter() + public static SearchFilter Equals(Expression> property, object value) => new ScalarFilter { IsData = true, DataType = typeof(T), @@ -41,26 +41,26 @@ public class DateRangeFilter : SearchFilter public DateTime? BeforeValue { get; set; } public DateTime? AfterValue { get; set; } - public static DateRangeFilter Before(Expression> property, DateTime value) => new DateRangeFilter() + public static DateRangeFilter Before(Expression> property, DateTime value) => new DateRangeFilter { Property = property, BeforeValue = value }; - public static DateRangeFilter After(Expression> property, DateTime value) => new DateRangeFilter() + public static DateRangeFilter After(Expression> property, DateTime value) => new DateRangeFilter { Property = property, AfterValue = value }; - public static DateRangeFilter Between(Expression> property, DateTime start, DateTime end) => new DateRangeFilter() + public static DateRangeFilter Between(Expression> property, DateTime start, DateTime end) => new DateRangeFilter { Property = property, BeforeValue = end, AfterValue = start }; - public static DateRangeFilter Before(Expression> property, DateTime value) => new DateRangeFilter() + public static DateRangeFilter Before(Expression> property, DateTime value) => new DateRangeFilter { IsData = true, DataType = typeof(T), @@ -68,7 +68,7 @@ public class DateRangeFilter : SearchFilter BeforeValue = value }; - public static DateRangeFilter After(Expression> property, DateTime value) => new DateRangeFilter() + public static DateRangeFilter After(Expression> property, DateTime value) => new DateRangeFilter { IsData = true, DataType = typeof(T), @@ -76,7 +76,7 @@ public class DateRangeFilter : SearchFilter AfterValue = value }; - public static DateRangeFilter Between(Expression> property, DateTime start, DateTime end) => new DateRangeFilter() + public static DateRangeFilter Between(Expression> property, DateTime start, DateTime end) => new DateRangeFilter { IsData = true, DataType = typeof(T), @@ -91,26 +91,26 @@ public class NumericRangeFilter : SearchFilter public double? LessValue { get; set; } public double? GreaterValue { get; set; } - public static NumericRangeFilter LessThan(Expression> property, double value) => new NumericRangeFilter() + public static NumericRangeFilter LessThan(Expression> property, double value) => new NumericRangeFilter { Property = property, LessValue = value }; - public static NumericRangeFilter GreaterThan(Expression> property, double value) => new NumericRangeFilter() + public static NumericRangeFilter GreaterThan(Expression> property, double value) => new NumericRangeFilter { Property = property, GreaterValue = value }; - public static NumericRangeFilter Between(Expression> property, double start, double end) => new NumericRangeFilter() + public static NumericRangeFilter Between(Expression> property, double start, double end) => new NumericRangeFilter { Property = property, LessValue = end, GreaterValue = start }; - public static NumericRangeFilter LessThan(Expression> property, double value) => new NumericRangeFilter() + public static NumericRangeFilter LessThan(Expression> property, double value) => new NumericRangeFilter { IsData = true, DataType = typeof(T), @@ -118,7 +118,7 @@ public class NumericRangeFilter : SearchFilter LessValue = value }; - public static NumericRangeFilter GreaterThan(Expression> property, double value) => new NumericRangeFilter() + public static NumericRangeFilter GreaterThan(Expression> property, double value) => new NumericRangeFilter { IsData = true, DataType = typeof(T), @@ -126,7 +126,7 @@ public class NumericRangeFilter : SearchFilter GreaterValue = value }; - public static NumericRangeFilter Between(Expression> property, double start, double end) => new NumericRangeFilter() + public static NumericRangeFilter Between(Expression> property, double start, double end) => new NumericRangeFilter { IsData = true, DataType = typeof(T), @@ -144,7 +144,7 @@ protected StatusFilter() Property = lambda; } - public static StatusFilter Equals(WorkflowStatus value) => new StatusFilter() + public static StatusFilter Equals(WorkflowStatus value) => new StatusFilter { Value = value.ToString() }; diff --git a/src/WorkflowCore/Models/StepBody.cs b/src/WorkflowCore/Models/StepBody.cs index 5ec927528..bb495c7a5 100644 --- a/src/WorkflowCore/Models/StepBody.cs +++ b/src/WorkflowCore/Models/StepBody.cs @@ -15,7 +15,7 @@ public Task RunAsync(IStepExecutionContext context) protected ExecutionResult OutcomeResult(object value) { - return new ExecutionResult() + return new ExecutionResult { Proceed = true, OutcomeValue = value @@ -24,7 +24,7 @@ protected ExecutionResult OutcomeResult(object value) protected ExecutionResult PersistResult(object persistenceData) { - return new ExecutionResult() + return new ExecutionResult { Proceed = false, PersistenceData = persistenceData @@ -33,7 +33,7 @@ protected ExecutionResult PersistResult(object persistenceData) protected ExecutionResult SleepResult(object persistenceData, TimeSpan sleep) { - return new ExecutionResult() + return new ExecutionResult { Proceed = false, PersistenceData = persistenceData, diff --git a/src/WorkflowCore/Primitives/Foreach.cs b/src/WorkflowCore/Primitives/Foreach.cs index d72371e56..1a64ddfdb 100644 --- a/src/WorkflowCore/Primitives/Foreach.cs +++ b/src/WorkflowCore/Primitives/Foreach.cs @@ -18,11 +18,11 @@ public override ExecutionResult Run(IStepExecutionContext context) var values = Collection.Cast(); if (RunParallel) { - return ExecutionResult.Branch(new List(values), new IteratorPersistenceData() { ChildrenActive = true }); + return ExecutionResult.Branch(new List(values), new IteratorPersistenceData { ChildrenActive = true }); } else { - return ExecutionResult.Branch(new List(new object[] { values.ElementAt(0) }), new IteratorPersistenceData() { ChildrenActive = true }); + return ExecutionResult.Branch(new List(new object[] { values.ElementAt(0) }), new IteratorPersistenceData { ChildrenActive = true }); } } diff --git a/src/WorkflowCore/Primitives/If.cs b/src/WorkflowCore/Primitives/If.cs index 1f7085788..b3950bf7c 100644 --- a/src/WorkflowCore/Primitives/If.cs +++ b/src/WorkflowCore/Primitives/If.cs @@ -15,7 +15,7 @@ public override ExecutionResult Run(IStepExecutionContext context) { if (Condition) { - return ExecutionResult.Branch(new List() { context.Item }, new ControlPersistenceData() { ChildrenActive = true }); + return ExecutionResult.Branch(new List { context.Item }, new ControlPersistenceData { ChildrenActive = true }); } return ExecutionResult.Next(); diff --git a/src/WorkflowCore/Primitives/OutcomeSwitch.cs b/src/WorkflowCore/Primitives/OutcomeSwitch.cs index d2dcc1e79..53cdc4729 100644 --- a/src/WorkflowCore/Primitives/OutcomeSwitch.cs +++ b/src/WorkflowCore/Primitives/OutcomeSwitch.cs @@ -12,7 +12,7 @@ public override ExecutionResult Run(IStepExecutionContext context) { if (context.PersistenceData == null) { - var result = ExecutionResult.Branch(new List() { context.Item }, new ControlPersistenceData() { ChildrenActive = true }); + var result = ExecutionResult.Branch(new List { context.Item }, new ControlPersistenceData { ChildrenActive = true }); result.OutcomeValue = GetPreviousOutcome(context); return result; } diff --git a/src/WorkflowCore/Primitives/Recur.cs b/src/WorkflowCore/Primitives/Recur.cs index ccc41e7d0..4b6189fb5 100644 --- a/src/WorkflowCore/Primitives/Recur.cs +++ b/src/WorkflowCore/Primitives/Recur.cs @@ -18,10 +18,10 @@ public override ExecutionResult Run(IStepExecutionContext context) return ExecutionResult.Next(); } - return new ExecutionResult() + return new ExecutionResult { Proceed = false, - BranchValues = new List() { null }, + BranchValues = new List { null }, SleepFor = Interval }; } diff --git a/src/WorkflowCore/Primitives/Schedule.cs b/src/WorkflowCore/Primitives/Schedule.cs index e279cb232..7eb63c8c1 100644 --- a/src/WorkflowCore/Primitives/Schedule.cs +++ b/src/WorkflowCore/Primitives/Schedule.cs @@ -13,14 +13,14 @@ public override ExecutionResult Run(IStepExecutionContext context) { if (context.PersistenceData == null) { - return ExecutionResult.Sleep(Interval, new SchedulePersistenceData() { Elapsed = false }); + return ExecutionResult.Sleep(Interval, new SchedulePersistenceData { Elapsed = false }); } if (context.PersistenceData is SchedulePersistenceData) { if (!((SchedulePersistenceData)context.PersistenceData).Elapsed) { - return ExecutionResult.Branch(new List() { context.Item }, new SchedulePersistenceData() { Elapsed = true }); + return ExecutionResult.Branch(new List { context.Item }, new SchedulePersistenceData { Elapsed = true }); } if (context.Workflow.IsBranchComplete(context.ExecutionPointer.Id)) diff --git a/src/WorkflowCore/Primitives/Sequence.cs b/src/WorkflowCore/Primitives/Sequence.cs index d31206a79..d3e0b827d 100644 --- a/src/WorkflowCore/Primitives/Sequence.cs +++ b/src/WorkflowCore/Primitives/Sequence.cs @@ -11,7 +11,7 @@ public override ExecutionResult Run(IStepExecutionContext context) { if (context.PersistenceData == null) { - return ExecutionResult.Branch(new List() { context.Item }, new ControlPersistenceData() { ChildrenActive = true }); + return ExecutionResult.Branch(new List { context.Item }, new ControlPersistenceData { ChildrenActive = true }); } if ((context.PersistenceData is ControlPersistenceData) && ((context.PersistenceData as ControlPersistenceData).ChildrenActive)) diff --git a/src/WorkflowCore/Primitives/When.cs b/src/WorkflowCore/Primitives/When.cs index f5f292ad1..a2ab32252 100644 --- a/src/WorkflowCore/Primitives/When.cs +++ b/src/WorkflowCore/Primitives/When.cs @@ -25,7 +25,7 @@ public override ExecutionResult Run(IStepExecutionContext context) if (context.PersistenceData == null) { - return ExecutionResult.Branch(new List() { context.Item }, new ControlPersistenceData() { ChildrenActive = true }); + return ExecutionResult.Branch(new List { context.Item }, new ControlPersistenceData { ChildrenActive = true }); } if ((context.PersistenceData is ControlPersistenceData) && ((context.PersistenceData as ControlPersistenceData).ChildrenActive)) diff --git a/src/WorkflowCore/Primitives/While.cs b/src/WorkflowCore/Primitives/While.cs index ba5abc2e6..7716ed0b0 100644 --- a/src/WorkflowCore/Primitives/While.cs +++ b/src/WorkflowCore/Primitives/While.cs @@ -15,7 +15,7 @@ public override ExecutionResult Run(IStepExecutionContext context) { if (Condition) { - return ExecutionResult.Branch(new List() { context.Item }, new ControlPersistenceData() { ChildrenActive = true }); + return ExecutionResult.Branch(new List { context.Item }, new ControlPersistenceData { ChildrenActive = true }); } return ExecutionResult.Next(); diff --git a/src/WorkflowCore/Services/ActivityController.cs b/src/WorkflowCore/Services/ActivityController.cs index f39bb64b2..04af6ef9f 100644 --- a/src/WorkflowCore/Services/ActivityController.cs +++ b/src/WorkflowCore/Services/ActivityController.cs @@ -47,7 +47,7 @@ public async Task GetPendingActivity(string activityName, strin try { var token = Token.Create(subscription.Id, subscription.EventKey); - var result = new PendingActivity() + var result = new PendingActivity { Token = token.Encode(), ActivityName = subscription.EventKey, @@ -75,7 +75,7 @@ public async Task ReleaseActivityToken(string token) public async Task SubmitActivitySuccess(string token, object result) { - await SubmitActivityResult(token, new ActivityResult() + await SubmitActivityResult(token, new ActivityResult { Data = result, Status = ActivityResult.StatusType.Success @@ -84,7 +84,7 @@ public async Task SubmitActivitySuccess(string token, object result) public async Task SubmitActivityFailure(string token, object result) { - await SubmitActivityResult(token, new ActivityResult() + await SubmitActivityResult(token, new ActivityResult { Data = result, Status = ActivityResult.StatusType.Fail @@ -120,7 +120,7 @@ public string Encode() public static Token Create(string subscriptionId, string activityName) { - return new Token() + return new Token { SubscriptionId = subscriptionId, ActivityName = activityName, diff --git a/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs index bdd730fca..9a5c825c4 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs @@ -60,7 +60,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance await _eventRepository.MarkEventProcessed(itemId); return; } - subs = new List() { activity }; + subs = new List { activity }; } else { diff --git a/src/WorkflowCore/Services/DefaultProviders/SingleNodeQueueProvider.cs b/src/WorkflowCore/Services/DefaultProviders/SingleNodeQueueProvider.cs index 8e0bd8dda..56f63b550 100644 --- a/src/WorkflowCore/Services/DefaultProviders/SingleNodeQueueProvider.cs +++ b/src/WorkflowCore/Services/DefaultProviders/SingleNodeQueueProvider.cs @@ -14,7 +14,7 @@ namespace WorkflowCore.Services public class SingleNodeQueueProvider : IQueueProvider { - private readonly Dictionary> _queues = new Dictionary>() + private readonly Dictionary> _queues = new Dictionary> { [QueueType.Workflow] = new BlockingCollection(), [QueueType.Event] = new BlockingCollection(), diff --git a/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs index 1cf6f7941..7c5fad05b 100755 --- a/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs @@ -22,7 +22,7 @@ public SuspendHandler(ILifeCycleEventPublisher eventPublisher, IDateTimeProvider public void Handle(WorkflowInstance workflow, WorkflowDefinition def, ExecutionPointer pointer, WorkflowStep step, Exception exception, Queue bubbleUpQueue) { workflow.Status = WorkflowStatus.Suspended; - _eventPublisher.PublishNotification(new WorkflowSuspended() + _eventPublisher.PublishNotification(new WorkflowSuspended { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, diff --git a/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs index d89f7f470..89fb05eae 100755 --- a/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs @@ -22,7 +22,7 @@ public TerminateHandler(ILifeCycleEventPublisher eventPublisher, IDateTimeProvid public void Handle(WorkflowInstance workflow, WorkflowDefinition def, ExecutionPointer pointer, WorkflowStep step, Exception exception, Queue bubbleUpQueue) { workflow.Status = WorkflowStatus.Terminated; - _eventPublisher.PublishNotification(new WorkflowTerminated() + _eventPublisher.PublishNotification(new WorkflowTerminated { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, diff --git a/src/WorkflowCore/Services/ExecutionPointerFactory.cs b/src/WorkflowCore/Services/ExecutionPointerFactory.cs index 65f5a2f8f..937e83d99 100644 --- a/src/WorkflowCore/Services/ExecutionPointerFactory.cs +++ b/src/WorkflowCore/Services/ExecutionPointerFactory.cs @@ -24,7 +24,7 @@ public ExecutionPointer BuildGenesisPointer(WorkflowDefinition def) public ExecutionPointer BuildNextPointer(WorkflowDefinition def, ExecutionPointer pointer, IStepOutcome outcomeTarget) { var nextId = GenerateId(); - return new ExecutionPointer() + return new ExecutionPointer { Id = nextId, PredecessorId = pointer.Id, @@ -44,7 +44,7 @@ public ExecutionPointer BuildChildPointer(WorkflowDefinition def, ExecutionPoint childScope.Insert(0, pointer.Id); pointer.Children.Add(childPointerId); - return new ExecutionPointer() + return new ExecutionPointer { Id = childPointerId, PredecessorId = pointer.Id, @@ -60,7 +60,7 @@ public ExecutionPointer BuildChildPointer(WorkflowDefinition def, ExecutionPoint public ExecutionPointer BuildCompensationPointer(WorkflowDefinition def, ExecutionPointer pointer, ExecutionPointer exceptionPointer, int compensationStepId) { var nextId = GenerateId(); - return new ExecutionPointer() + return new ExecutionPointer { Id = nextId, PredecessorId = exceptionPointer.Id, diff --git a/src/WorkflowCore/Services/ExecutionResultProcessor.cs b/src/WorkflowCore/Services/ExecutionResultProcessor.cs index 781f3d39d..3c684945f 100755 --- a/src/WorkflowCore/Services/ExecutionResultProcessor.cs +++ b/src/WorkflowCore/Services/ExecutionResultProcessor.cs @@ -44,7 +44,7 @@ public void ProcessExecutionResult(WorkflowInstance workflow, WorkflowDefinition pointer.Active = false; pointer.Status = PointerStatus.WaitingForEvent; - workflowResult.Subscriptions.Add(new EventSubscription() + workflowResult.Subscriptions.Add(new EventSubscription { WorkflowId = workflow.Id, StepId = pointer.StepId, @@ -77,7 +77,7 @@ public void ProcessExecutionResult(WorkflowInstance workflow, WorkflowDefinition subsequent.Active = true; } - _eventPublisher.PublishNotification(new StepCompleted() + _eventPublisher.PublishNotification(new StepCompleted { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, @@ -102,7 +102,7 @@ public void ProcessExecutionResult(WorkflowInstance workflow, WorkflowDefinition public void HandleStepException(WorkflowInstance workflow, WorkflowDefinition def, ExecutionPointer pointer, WorkflowStep step, Exception exception) { - _eventPublisher.PublishNotification(new WorkflowError() + _eventPublisher.PublishNotification(new WorkflowError { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, diff --git a/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs b/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs index e1d4dcc76..f5d25730a 100644 --- a/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs +++ b/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs @@ -45,7 +45,7 @@ public IStepBuilder Then(Action> } newStep.Name = newStep.Name ?? typeof(TStep).Name; - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } @@ -53,7 +53,7 @@ public IStepBuilder Then(Action> public IStepBuilder Then(IStepBuilder newStep) where TStep : IStepBody { - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Step.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Step.Id }); var stepBuilder = new StepBuilder(WorkflowBuilder, newStep.Step); return stepBuilder; } @@ -64,7 +64,7 @@ public IStepBuilder Then(Func(WorkflowBuilder, newStep); - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } @@ -74,13 +74,13 @@ public IStepBuilder Then(Action bo WorkflowBuilder.AddStep(newStep); var stepBuilder = new StepBuilder(WorkflowBuilder, newStep); stepBuilder.Input(x => x.Body, x => body); - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } public IStepBuilder Attach(string id) { - Step.Outcomes.Add(new ValueOutcome() + Step.Outcomes.Add(new ValueOutcome { ExternalNextStepId = id }); @@ -184,7 +184,7 @@ public IStepBuilder WaitFor(string eventName, Expression step.EffectiveDate, effectiveDate); } - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } @@ -203,7 +203,7 @@ public IStepBuilder WaitFor(string eventName, Expression step.EffectiveDate, effectiveDate); } - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } @@ -259,7 +259,7 @@ public IStepBuilder EndWorkflow() { EndStep newStep = new EndStep(); WorkflowBuilder.AddStep(newStep); - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return this; } @@ -272,7 +272,7 @@ public IStepBuilder Delay(Expression> period WorkflowBuilder.AddStep(newStep); var stepBuilder = new StepBuilder(WorkflowBuilder, newStep); - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } @@ -286,7 +286,7 @@ public IStepBuilder Decide(Expression> expres WorkflowBuilder.AddStep(newStep); var stepBuilder = new StepBuilder(WorkflowBuilder, newStep); - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } @@ -301,7 +301,7 @@ public IContainerStepBuilder ForEach(Expression(WorkflowBuilder, newStep); - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } @@ -319,7 +319,7 @@ public IContainerStepBuilder ForEach(Expression(WorkflowBuilder, newStep); - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } @@ -335,7 +335,7 @@ public IContainerStepBuilder While(Expression(WorkflowBuilder, newStep); - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } @@ -350,7 +350,7 @@ public IContainerStepBuilder If(Expression> con WorkflowBuilder.AddStep(newStep); var stepBuilder = new StepBuilder(WorkflowBuilder, newStep); - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } @@ -367,7 +367,7 @@ public IContainerStepBuilder When(Expression(); WorkflowBuilder.AddStep(switchStep); - Step.Outcomes.Add(new ValueOutcome() + Step.Outcomes.Add(new ValueOutcome { NextStep = switchStep.Id, Label = label @@ -391,7 +391,7 @@ public IStepBuilder Saga(Action> builde var newStep = new SagaContainer(); WorkflowBuilder.AddStep(newStep); var stepBuilder = new StepBuilder(WorkflowBuilder, newStep); - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); builder.Invoke(WorkflowBuilder); stepBuilder.Step.Children.Add(stepBuilder.Step.Id + 1); //TODO: make more elegant @@ -405,7 +405,7 @@ public IParallelStepBuilder Parallel() WorkflowBuilder.AddStep(newStep); var stepBuilder = new ParallelStepBuilder(WorkflowBuilder, newBuilder, newBuilder); - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } @@ -418,7 +418,7 @@ public IContainerStepBuilder Schedule(Expression(WorkflowBuilder, newStep, this); - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } @@ -435,7 +435,7 @@ public IContainerStepBuilder Recur(Expression(WorkflowBuilder, newStep, this); - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } @@ -519,7 +519,7 @@ public IStepBuilder Activity(string activityName, Expression step.EffectiveDate, effectiveDate); - Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } } diff --git a/src/WorkflowCore/Services/WorkflowController.cs b/src/WorkflowCore/Services/WorkflowController.cs index 690a6a596..576c1b981 100755 --- a/src/WorkflowCore/Services/WorkflowController.cs +++ b/src/WorkflowCore/Services/WorkflowController.cs @@ -94,7 +94,7 @@ public async Task StartWorkflow(string workflowId, int? version, string id = await _persistenceStore.CreateNewWorkflow(wf); await _queueProvider.QueueWork(id, QueueType.Workflow); await _queueProvider.QueueWork(id, QueueType.Index); - await _eventHub.PublishNotification(new WorkflowStarted() + await _eventHub.PublishNotification(new WorkflowStarted { EventTimeUtc = _dateTimeProvider.UtcNow, Reference = reference, @@ -137,7 +137,7 @@ public async Task SuspendWorkflow(string workflowId) wf.Status = WorkflowStatus.Suspended; await _persistenceStore.PersistWorkflow(wf); await _queueProvider.QueueWork(workflowId, QueueType.Index); - await _eventHub.PublishNotification(new WorkflowSuspended() + await _eventHub.PublishNotification(new WorkflowSuspended { EventTimeUtc = _dateTimeProvider.UtcNow, Reference = wf.Reference, @@ -173,7 +173,7 @@ public async Task ResumeWorkflow(string workflowId) await _persistenceStore.PersistWorkflow(wf); requeue = true; await _queueProvider.QueueWork(workflowId, QueueType.Index); - await _eventHub.PublishNotification(new WorkflowResumed() + await _eventHub.PublishNotification(new WorkflowResumed { EventTimeUtc = _dateTimeProvider.UtcNow, Reference = wf.Reference, @@ -207,7 +207,7 @@ public async Task TerminateWorkflow(string workflowId) wf.Status = WorkflowStatus.Terminated; await _persistenceStore.PersistWorkflow(wf); await _queueProvider.QueueWork(workflowId, QueueType.Index); - await _eventHub.PublishNotification(new WorkflowTerminated() + await _eventHub.PublishNotification(new WorkflowTerminated { EventTimeUtc = _dateTimeProvider.UtcNow, Reference = wf.Reference, diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index c6241fd64..6ba2ce564 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -62,7 +62,7 @@ public async Task Execute(WorkflowInstance workflow, Can { _logger.LogError("Unable to find step {0} in workflow definition", pointer.StepId); pointer.SleepUntil = _datetimeProvider.UtcNow.Add(_options.ErrorRetryInterval); - wfResult.Errors.Add(new ExecutionError() + wfResult.Errors.Add(new ExecutionError { WorkflowId = workflow.Id, ExecutionPointerId = pointer.Id, @@ -82,7 +82,7 @@ public async Task Execute(WorkflowInstance workflow, Can catch (Exception ex) { _logger.LogError(ex, "Workflow {0} raised error on step {1} Message: {2}", workflow.Id, pointer.StepId, ex.Message); - wfResult.Errors.Add(new ExecutionError() + wfResult.Errors.Add(new ExecutionError { WorkflowId = workflow.Id, ExecutionPointerId = pointer.Id, @@ -116,7 +116,7 @@ private bool InitializeStep(WorkflowInstance workflow, WorkflowStep step, Workfl if (pointer.Status != PointerStatus.Running) { pointer.Status = PointerStatus.Running; - _publisher.PublishNotification(new StepStarted() + _publisher.PublishNotification(new StepStarted { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, @@ -138,7 +138,7 @@ private bool InitializeStep(WorkflowInstance workflow, WorkflowStep step, Workfl private async Task ExecuteStep(WorkflowInstance workflow, WorkflowStep step, ExecutionPointer pointer, WorkflowExecutorResult wfResult, WorkflowDefinition def, CancellationToken cancellationToken = default) { - IStepExecutionContext context = new StepExecutionContext() + IStepExecutionContext context = new StepExecutionContext { Workflow = workflow, Step = step, @@ -159,7 +159,7 @@ private async Task ExecuteStep(WorkflowInstance workflow, WorkflowStep step, Exe { _logger.LogError("Unable to construct step body {0}", step.BodyType.ToString()); pointer.SleepUntil = _datetimeProvider.UtcNow.Add(_options.ErrorRetryInterval); - wfResult.Errors.Add(new ExecutionError() + wfResult.Errors.Add(new ExecutionError { WorkflowId = workflow.Id, ExecutionPointerId = pointer.Id, @@ -253,7 +253,7 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo await middlewareRunner.RunPostMiddleware(workflow, def); } - _publisher.PublishNotification(new WorkflowCompleted() + _publisher.PublishNotification(new WorkflowCompleted { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, diff --git a/src/extensions/WorkflowCore.Users/Models/UserStepContainer.cs b/src/extensions/WorkflowCore.Users/Models/UserStepContainer.cs index 901bd28b7..0b3b348e4 100644 --- a/src/extensions/WorkflowCore.Users/Models/UserStepContainer.cs +++ b/src/extensions/WorkflowCore.Users/Models/UserStepContainer.cs @@ -39,7 +39,7 @@ public override ExecutionPipelineDirective InitForExecution(WorkflowExecutorResu executionPointer.EventName = "UserAction"; executionPointer.Active = false; - executorResult.Subscriptions.Add(new EventSubscription() + executorResult.Subscriptions.Add(new EventSubscription { WorkflowId = workflow.Id, StepId = executionPointer.StepId, diff --git a/src/extensions/WorkflowCore.Users/Primitives/UserTask.cs b/src/extensions/WorkflowCore.Users/Primitives/UserTask.cs index a1edd9b72..7772a894c 100644 --- a/src/extensions/WorkflowCore.Users/Primitives/UserTask.cs +++ b/src/extensions/WorkflowCore.Users/Primitives/UserTask.cs @@ -50,7 +50,7 @@ public override ExecutionResult Run(IStepExecutionContext context) if (context.PersistenceData == null) { - var result = ExecutionResult.Branch(new List() { context.Item }, new ControlPersistenceData() { ChildrenActive = true }); + var result = ExecutionResult.Branch(new List { context.Item }, new ControlPersistenceData { ChildrenActive = true }); result.OutcomeValue = action.OutcomeValue; return result; } @@ -74,7 +74,7 @@ private void SetupEscalations(IStepExecutionContext context) { foreach (var esc in _escalations) { - context.Workflow.ExecutionPointers.Add(new ExecutionPointer() + context.Workflow.ExecutionPointers.Add(new ExecutionPointer { Active = true, Id = Guid.NewGuid().ToString(), diff --git a/src/extensions/WorkflowCore.Users/ServiceExtensions/StepBuilderExtensions.cs b/src/extensions/WorkflowCore.Users/ServiceExtensions/StepBuilderExtensions.cs index 44e9e1ce7..3330c123b 100644 --- a/src/extensions/WorkflowCore.Users/ServiceExtensions/StepBuilderExtensions.cs +++ b/src/extensions/WorkflowCore.Users/ServiceExtensions/StepBuilderExtensions.cs @@ -30,7 +30,7 @@ public static IStepBuilder UserStep(this ISte stepSetup.Invoke(stepBuilder); newStep.Name = newStep.Name ?? typeof(UserStepContainer).Name; - builder.Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + builder.Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } @@ -64,7 +64,7 @@ public static IUserTaskBuilder UserTask(this IStepBuild stepSetup.Invoke(stepBuilder); newStep.Name = newStep.Name ?? typeof(UserTask).Name; - builder.Step.Outcomes.Add(new ValueOutcome() { NextStep = newStep.Id }); + builder.Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); return stepBuilder; } diff --git a/src/extensions/WorkflowCore.Users/ServiceExtensions/WorkflowHostExtensions.cs b/src/extensions/WorkflowCore.Users/ServiceExtensions/WorkflowHostExtensions.cs index dbb44becc..89b753f52 100644 --- a/src/extensions/WorkflowCore.Users/ServiceExtensions/WorkflowHostExtensions.cs +++ b/src/extensions/WorkflowCore.Users/ServiceExtensions/WorkflowHostExtensions.cs @@ -15,7 +15,7 @@ public static class WorkflowHostExtensions { public static async Task PublishUserAction(this IWorkflowHost host, string actionKey, string user, object value) { - UserAction data = new UserAction() + UserAction data = new UserAction { User = user, OutcomeValue = value diff --git a/src/extensions/WorkflowCore.Users/ServiceExtensions/WorkflowInstanceExtensions.cs b/src/extensions/WorkflowCore.Users/ServiceExtensions/WorkflowInstanceExtensions.cs index de44c011b..464cedd14 100644 --- a/src/extensions/WorkflowCore.Users/ServiceExtensions/WorkflowInstanceExtensions.cs +++ b/src/extensions/WorkflowCore.Users/ServiceExtensions/WorkflowInstanceExtensions.cs @@ -14,7 +14,7 @@ public static IEnumerable GetOpenUserActions(this WorkflowInstan var pointers = workflow.ExecutionPointers.Where(x => !x.EventPublished && x.EventName == UserTask.EventName).ToList(); foreach (var pointer in pointers) { - var item = new OpenUserAction() + var item = new OpenUserAction { Key = pointer.EventKey, Prompt = Convert.ToString(pointer.ExtensionAttributes[UserTask.ExtPrompt]), diff --git a/src/extensions/WorkflowCore.Users/Services/UserTaskBuilder.cs b/src/extensions/WorkflowCore.Users/Services/UserTaskBuilder.cs index ce241ab52..5ea5da8db 100644 --- a/src/extensions/WorkflowCore.Users/Services/UserTaskBuilder.cs +++ b/src/extensions/WorkflowCore.Users/Services/UserTaskBuilder.cs @@ -53,7 +53,7 @@ public IUserTaskBuilder WithEscalation(Expression> var lastStep = WorkflowBuilder.LastStep; action.Invoke(WorkflowBuilder); if (WorkflowBuilder.LastStep > lastStep) - newStep.Outcomes.Add(new ValueOutcome() { NextStep = lastStep + 1 }); + newStep.Outcomes.Add(new ValueOutcome { NextStep = lastStep + 1 }); } return this; diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs index cf3f9183c..ae0659968 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs @@ -10,7 +10,7 @@ namespace WorkflowCore.Persistence.EntityFramework { internal static class ExtensionMethods { - private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; + private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; internal static PersistedWorkflow ToPersistable(this WorkflowInstance instance, PersistedWorkflow persistable = null) { diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs index 2cf6cab3e..dfa5f75fb 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/DataObjectSerializer.cs @@ -11,7 +11,7 @@ namespace WorkflowCore.Persistence.MongoDB.Services { public class DataObjectSerializer : SerializerBase { - private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() + private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, }; diff --git a/src/providers/WorkflowCore.Providers.AWS/ModelExtensions.cs b/src/providers/WorkflowCore.Providers.AWS/ModelExtensions.cs index 6ec9b0f8b..62f9cf38e 100644 --- a/src/providers/WorkflowCore.Providers.AWS/ModelExtensions.cs +++ b/src/providers/WorkflowCore.Providers.AWS/ModelExtensions.cs @@ -12,7 +12,7 @@ namespace WorkflowCore.Providers.AWS { internal static class ModelExtensions { - private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; + private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; public static Dictionary ToDynamoMap(this WorkflowInstance source) { @@ -21,10 +21,10 @@ public static Dictionary ToDynamoMap(this WorkflowInstan result["id"] = new AttributeValue(source.Id); result["workflow_definition_id"] = new AttributeValue(source.WorkflowDefinitionId); result["version"] = new AttributeValue(source.Version.ToString()); - result["next_execution"] = new AttributeValue() { N = (source.NextExecution ?? 0).ToString() }; - result["create_time"] = new AttributeValue() { N = source.CreateTime.Ticks.ToString() }; + result["next_execution"] = new AttributeValue { N = (source.NextExecution ?? 0).ToString() }; + result["create_time"] = new AttributeValue { N = source.CreateTime.Ticks.ToString() }; result["data"] = new AttributeValue(JsonConvert.SerializeObject(source.Data, SerializerSettings)); - result["workflow_status"] = new AttributeValue() { N = Convert.ToInt32(source.Status).ToString() }; + result["workflow_status"] = new AttributeValue { N = Convert.ToInt32(source.Status).ToString() }; if (!string.IsNullOrEmpty(source.Description)) result["description"] = new AttributeValue(source.Description); @@ -33,7 +33,7 @@ public static Dictionary ToDynamoMap(this WorkflowInstan result["reference"] = new AttributeValue(source.Reference); if (source.CompleteTime.HasValue) - result["complete_time"] = new AttributeValue() { N = source.CompleteTime.Value.Ticks.ToString() }; + result["complete_time"] = new AttributeValue { N = source.CompleteTime.Value.Ticks.ToString() }; var pointers = new List(); foreach (var pointer in source.ExecutionPointers) @@ -41,17 +41,17 @@ public static Dictionary ToDynamoMap(this WorkflowInstan pointers.Add(new AttributeValue(JsonConvert.SerializeObject(pointer, SerializerSettings))); } - result["pointers"] = new AttributeValue() { L = pointers }; + result["pointers"] = new AttributeValue { L = pointers }; if (source.Status == WorkflowStatus.Runnable) - result["runnable"] = new AttributeValue() { N = 1.ToString() }; + result["runnable"] = new AttributeValue { N = 1.ToString() }; return result; } public static WorkflowInstance ToWorkflowInstance(this Dictionary source) { - var result = new WorkflowInstance() + var result = new WorkflowInstance { Id = source["id"].S, WorkflowDefinitionId = source["workflow_definition_id"].S, @@ -90,7 +90,7 @@ public static Dictionary ToDynamoMap(this EventSubscript ["workflow_id"] = new AttributeValue(source.WorkflowId), ["execution_pointer_id"] = new AttributeValue(source.ExecutionPointerId), ["step_id"] = new AttributeValue(source.StepId.ToString()), - ["subscribe_as_of"] = new AttributeValue() { N = source.SubscribeAsOf.Ticks.ToString() }, + ["subscribe_as_of"] = new AttributeValue { N = source.SubscribeAsOf.Ticks.ToString() }, ["subscription_data"] = new AttributeValue(JsonConvert.SerializeObject(source.SubscriptionData, SerializerSettings)), ["event_slug"] = new AttributeValue($"{source.EventName}:{source.EventKey}") }; @@ -101,14 +101,14 @@ public static Dictionary ToDynamoMap(this EventSubscript result["external_worker_id"] = new AttributeValue(source.ExternalWorkerId); if (source.ExternalTokenExpiry.HasValue) - result["external_token_expiry"] = new AttributeValue() { N = source.ExternalTokenExpiry.Value.Ticks.ToString()}; + result["external_token_expiry"] = new AttributeValue { N = source.ExternalTokenExpiry.Value.Ticks.ToString()}; return result; } public static EventSubscription ToEventSubscription(this Dictionary source) { - var result = new EventSubscription() + var result = new EventSubscription { Id = source["id"].S, EventName = source["event_name"].S, @@ -140,19 +140,19 @@ public static Dictionary ToDynamoMap(this Event source) ["event_name"] = new AttributeValue(source.EventName), ["event_key"] = new AttributeValue(source.EventKey), ["event_data"] = new AttributeValue(JsonConvert.SerializeObject(source.EventData, SerializerSettings)), - ["event_time"] = new AttributeValue() { N = source.EventTime.Ticks.ToString() }, + ["event_time"] = new AttributeValue { N = source.EventTime.Ticks.ToString() }, ["event_slug"] = new AttributeValue($"{source.EventName}:{source.EventKey}") }; if (!source.IsProcessed) - result["not_processed"] = new AttributeValue() { N = 1.ToString() }; + result["not_processed"] = new AttributeValue { N = 1.ToString() }; return result; } public static Event ToEvent(this Dictionary source) { - var result = new Event() + var result = new Event { Id = source["id"].S, EventName = source["event_name"].S, diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs index a78b006c0..a6bb72662 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs @@ -33,10 +33,10 @@ public Task ProvisionTables() private async Task CreateWorkflowTable() { - var runnableIndex = new GlobalSecondaryIndex() + var runnableIndex = new GlobalSecondaryIndex { IndexName = "ix_runnable", - KeySchema = new List() + KeySchema = new List { { new KeySchemaElement @@ -53,33 +53,33 @@ private async Task CreateWorkflowTable() } } }, - Projection = new Projection() + Projection = new Projection { ProjectionType = ProjectionType.KEYS_ONLY }, - ProvisionedThroughput = new ProvisionedThroughput() + ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 1, WriteCapacityUnits = 1 } }; - var createRequest = new CreateTableRequest($"{_tablePrefix}-{DynamoPersistenceProvider.WORKFLOW_TABLE}", new List() + var createRequest = new CreateTableRequest($"{_tablePrefix}-{DynamoPersistenceProvider.WORKFLOW_TABLE}", new List { new KeySchemaElement("id", KeyType.HASH) }) { - AttributeDefinitions = new List() + AttributeDefinitions = new List { new AttributeDefinition("id", ScalarAttributeType.S), new AttributeDefinition("runnable", ScalarAttributeType.N), new AttributeDefinition("next_execution", ScalarAttributeType.N), }, - GlobalSecondaryIndexes = new List() + GlobalSecondaryIndexes = new List { runnableIndex }, - ProvisionedThroughput = new ProvisionedThroughput() + ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 1, WriteCapacityUnits = 1 @@ -91,10 +91,10 @@ private async Task CreateWorkflowTable() private async Task CreateSubscriptionTable() { - var slugIndex = new GlobalSecondaryIndex() + var slugIndex = new GlobalSecondaryIndex { IndexName = "ix_slug", - KeySchema = new List() + KeySchema = new List { { new KeySchemaElement @@ -111,33 +111,33 @@ private async Task CreateSubscriptionTable() } } }, - Projection = new Projection() + Projection = new Projection { ProjectionType = ProjectionType.ALL }, - ProvisionedThroughput = new ProvisionedThroughput() + ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 1, WriteCapacityUnits = 1 } }; - var createRequest = new CreateTableRequest($"{_tablePrefix}-{DynamoPersistenceProvider.SUBCRIPTION_TABLE}", new List() + var createRequest = new CreateTableRequest($"{_tablePrefix}-{DynamoPersistenceProvider.SUBCRIPTION_TABLE}", new List { new KeySchemaElement("id", KeyType.HASH) }) { - AttributeDefinitions = new List() + AttributeDefinitions = new List { new AttributeDefinition("id", ScalarAttributeType.S), new AttributeDefinition("event_slug", ScalarAttributeType.S), new AttributeDefinition("subscribe_as_of", ScalarAttributeType.N) }, - GlobalSecondaryIndexes = new List() + GlobalSecondaryIndexes = new List { slugIndex }, - ProvisionedThroughput = new ProvisionedThroughput() + ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 1, WriteCapacityUnits = 1 @@ -149,10 +149,10 @@ private async Task CreateSubscriptionTable() private async Task CreateEventTable() { - var slugIndex = new GlobalSecondaryIndex() + var slugIndex = new GlobalSecondaryIndex { IndexName = "ix_slug", - KeySchema = new List() + KeySchema = new List { { new KeySchemaElement @@ -169,21 +169,21 @@ private async Task CreateEventTable() } } }, - Projection = new Projection() + Projection = new Projection { ProjectionType = ProjectionType.KEYS_ONLY }, - ProvisionedThroughput = new ProvisionedThroughput() + ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 1, WriteCapacityUnits = 1 } }; - var processedIndex = new GlobalSecondaryIndex() + var processedIndex = new GlobalSecondaryIndex { IndexName = "ix_not_processed", - KeySchema = new List() + KeySchema = new List { { new KeySchemaElement @@ -200,35 +200,35 @@ private async Task CreateEventTable() } } }, - Projection = new Projection() + Projection = new Projection { ProjectionType = ProjectionType.KEYS_ONLY }, - ProvisionedThroughput = new ProvisionedThroughput() + ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 1, WriteCapacityUnits = 1 } }; - var createRequest = new CreateTableRequest($"{_tablePrefix}-{DynamoPersistenceProvider.EVENT_TABLE}", new List() + var createRequest = new CreateTableRequest($"{_tablePrefix}-{DynamoPersistenceProvider.EVENT_TABLE}", new List { new KeySchemaElement("id", KeyType.HASH) }) { - AttributeDefinitions = new List() + AttributeDefinitions = new List { new AttributeDefinition("id", ScalarAttributeType.S), new AttributeDefinition("not_processed", ScalarAttributeType.N), new AttributeDefinition("event_slug", ScalarAttributeType.S), new AttributeDefinition("event_time", ScalarAttributeType.N) }, - GlobalSecondaryIndexes = new List() + GlobalSecondaryIndexes = new List { slugIndex, processedIndex }, - ProvisionedThroughput = new ProvisionedThroughput() + ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 1, WriteCapacityUnits = 1 diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs index b10dc4365..6f4aca0e8 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs @@ -39,14 +39,14 @@ public async Task AcquireLock(string Id, CancellationToken cancellationTok { try { - var req = new PutItemRequest() + var req = new PutItemRequest { TableName = _tableName, Item = new Dictionary { { "id", new AttributeValue(Id) }, { "lock_owner", new AttributeValue(_nodeId) }, - { "expires", new AttributeValue() + { "expires", new AttributeValue { N = Convert.ToString(new DateTimeOffset(_dateTimeProvider.UtcNow).ToUnixTimeMilliseconds() + _ttl) } @@ -55,7 +55,7 @@ public async Task AcquireLock(string Id, CancellationToken cancellationTok ConditionExpression = "attribute_not_exists(id) OR (expires < :expired)", ExpressionAttributeValues = new Dictionary { - { ":expired", new AttributeValue() + { ":expired", new AttributeValue { N = Convert.ToString(new DateTimeOffset(_dateTimeProvider.UtcNow).ToUnixTimeMilliseconds() + _jitter) } @@ -91,7 +91,7 @@ public async Task ReleaseLock(string Id) try { - var req = new DeleteItemRequest() + var req = new DeleteItemRequest { TableName = _tableName, Key = new Dictionary @@ -154,7 +154,7 @@ private async void SendHeartbeat() { { "id", new AttributeValue(item) }, { "lock_owner", new AttributeValue(_nodeId) }, - { "expires", new AttributeValue() + { "expires", new AttributeValue { N = Convert.ToString(new DateTimeOffset(_dateTimeProvider.UtcNow).ToUnixTimeMilliseconds() + _ttl) } @@ -204,12 +204,12 @@ private async Task EnsureTable() private async Task CreateTable() { - var createRequest = new CreateTableRequest(_tableName, new List() + var createRequest = new CreateTableRequest(_tableName, new List { new KeySchemaElement("id", KeyType.HASH) }) { - AttributeDefinitions = new List() + AttributeDefinitions = new List { new AttributeDefinition("id", ScalarAttributeType.S) }, diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs index afc531b7a..69ba8eaf1 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs @@ -36,7 +36,7 @@ public async Task CreateNewWorkflow(WorkflowInstance workflow) { workflow.Id = Guid.NewGuid().ToString(); - var req = new PutItemRequest() + var req = new PutItemRequest { TableName = $"{_tablePrefix}-{WORKFLOW_TABLE}", Item = workflow.ToDynamoMap(), @@ -50,7 +50,7 @@ public async Task CreateNewWorkflow(WorkflowInstance workflow) public async Task PersistWorkflow(WorkflowInstance workflow) { - var request = new PutItemRequest() + var request = new PutItemRequest { TableName = $"{_tablePrefix}-{WORKFLOW_TABLE}", Item = workflow.ToDynamoMap() @@ -64,7 +64,7 @@ public async Task> GetRunnableInstances(DateTime asAt) var result = new List(); var now = asAt.ToUniversalTime().Ticks; - var request = new QueryRequest() + var request = new QueryRequest { TableName = $"{_tablePrefix}-{WORKFLOW_TABLE}", IndexName = "ix_runnable", @@ -73,13 +73,13 @@ public async Task> GetRunnableInstances(DateTime asAt) ExpressionAttributeValues = new Dictionary { { - ":r", new AttributeValue() + ":r", new AttributeValue { N = 1.ToString() } }, { - ":effective_date", new AttributeValue() + ":effective_date", new AttributeValue { N = Convert.ToString(now) } @@ -105,7 +105,7 @@ public Task> GetWorkflowInstances(WorkflowStatus? public async Task GetWorkflowInstance(string Id) { - var req = new GetItemRequest() + var req = new GetItemRequest { TableName = $"{_tablePrefix}-{WORKFLOW_TABLE}", Key = new Dictionary @@ -125,10 +125,10 @@ public async Task> GetWorkflowInstances(IEnumerabl return new List(); } - var keys = new KeysAndAttributes() { Keys = new List>() }; + var keys = new KeysAndAttributes { Keys = new List>() }; foreach (var id in ids) { - var key = new Dictionary() + var key = new Dictionary { { "id", new AttributeValue { S = id } @@ -139,7 +139,7 @@ public async Task> GetWorkflowInstances(IEnumerabl var request = new BatchGetItemRequest { - RequestItems = new Dictionary() + RequestItems = new Dictionary { { $"{_tablePrefix}-{WORKFLOW_TABLE}", keys @@ -165,7 +165,7 @@ public async Task CreateEventSubscription(EventSubscription subscription { subscription.Id = Guid.NewGuid().ToString(); - var req = new PutItemRequest() + var req = new PutItemRequest { TableName = $"{_tablePrefix}-{SUBCRIPTION_TABLE}", Item = subscription.ToDynamoMap(), @@ -182,7 +182,7 @@ public async Task> GetSubscriptions(string eventN var result = new List(); var asOfTicks = asOf.ToUniversalTime().Ticks; - var request = new QueryRequest() + var request = new QueryRequest { TableName = $"{_tablePrefix}-{SUBCRIPTION_TABLE}", IndexName = "ix_slug", @@ -194,7 +194,7 @@ public async Task> GetSubscriptions(string eventN ":slug", new AttributeValue($"{eventName}:{eventKey}") }, { - ":as_of", new AttributeValue() + ":as_of", new AttributeValue { N = Convert.ToString(asOfTicks) } @@ -215,7 +215,7 @@ public async Task> GetSubscriptions(string eventN public async Task TerminateSubscription(string eventSubscriptionId) { - var request = new DeleteItemRequest() + var request = new DeleteItemRequest { TableName = $"{_tablePrefix}-{SUBCRIPTION_TABLE}", Key = new Dictionary @@ -230,7 +230,7 @@ public async Task CreateEvent(Event newEvent) { newEvent.Id = Guid.NewGuid().ToString(); - var req = new PutItemRequest() + var req = new PutItemRequest { TableName = $"{_tablePrefix}-{EVENT_TABLE}", Item = newEvent.ToDynamoMap(), @@ -244,7 +244,7 @@ public async Task CreateEvent(Event newEvent) public async Task GetEvent(string id) { - var req = new GetItemRequest() + var req = new GetItemRequest { TableName = $"{_tablePrefix}-{EVENT_TABLE}", Key = new Dictionary @@ -262,7 +262,7 @@ public async Task> GetRunnableEvents(DateTime asAt) var result = new List(); var now = asAt.ToUniversalTime().Ticks; - var request = new QueryRequest() + var request = new QueryRequest { TableName = $"{_tablePrefix}-{EVENT_TABLE}", IndexName = "ix_not_processed", @@ -270,9 +270,9 @@ public async Task> GetRunnableEvents(DateTime asAt) KeyConditionExpression = "not_processed = :n and event_time <= :effectiveDate", ExpressionAttributeValues = new Dictionary { - { ":n" , new AttributeValue() { N = 1.ToString() } }, + { ":n" , new AttributeValue { N = 1.ToString() } }, { - ":effectiveDate", new AttributeValue() + ":effectiveDate", new AttributeValue { N = Convert.ToString(now) } @@ -296,7 +296,7 @@ public async Task> GetEvents(string eventName, string eventK var result = new List(); var asOfTicks = asOf.ToUniversalTime().Ticks; - var request = new QueryRequest() + var request = new QueryRequest { TableName = $"{_tablePrefix}-{EVENT_TABLE}", IndexName = "ix_slug", @@ -308,7 +308,7 @@ public async Task> GetEvents(string eventName, string eventK ":slug", new AttributeValue($"{eventName}:{eventKey}") }, { - ":effective_date", new AttributeValue() + ":effective_date", new AttributeValue { N = Convert.ToString(asOfTicks) } @@ -329,7 +329,7 @@ public async Task> GetEvents(string eventName, string eventK public async Task MarkEventProcessed(string id) { - var request = new UpdateItemRequest() + var request = new UpdateItemRequest { TableName = $"{_tablePrefix}-{EVENT_TABLE}", Key = new Dictionary @@ -343,7 +343,7 @@ public async Task MarkEventProcessed(string id) public async Task MarkEventUnprocessed(string id) { - var request = new UpdateItemRequest() + var request = new UpdateItemRequest { TableName = $"{_tablePrefix}-{EVENT_TABLE}", Key = new Dictionary @@ -351,9 +351,9 @@ public async Task MarkEventUnprocessed(string id) { "id", new AttributeValue(id) } }, UpdateExpression = "ADD not_processed = :n", - ExpressionAttributeValues = new Dictionary() + ExpressionAttributeValues = new Dictionary { - { ":n" , new AttributeValue() { N = 1.ToString() } } + { ":n" , new AttributeValue { N = 1.ToString() } } } }; await _client.UpdateItemAsync(request); @@ -372,7 +372,7 @@ public void EnsureStoreExists() public async Task GetSubscription(string eventSubscriptionId) { - var req = new GetItemRequest() + var req = new GetItemRequest { TableName = $"{_tablePrefix}-{SUBCRIPTION_TABLE}", Key = new Dictionary @@ -390,7 +390,7 @@ public async Task GetFirstOpenSubscription(string eventName, var result = new List(); var asOfTicks = asOf.ToUniversalTime().Ticks; - var request = new QueryRequest() + var request = new QueryRequest { TableName = $"{_tablePrefix}-{SUBCRIPTION_TABLE}", IndexName = "ix_slug", @@ -404,7 +404,7 @@ public async Task GetFirstOpenSubscription(string eventName, ":slug", new AttributeValue($"{eventName}:{eventKey}") }, { - ":as_of", new AttributeValue() + ":as_of", new AttributeValue { N = Convert.ToString(asOfTicks) } @@ -423,7 +423,7 @@ public async Task GetFirstOpenSubscription(string eventName, public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry) { - var request = new UpdateItemRequest() + var request = new UpdateItemRequest { TableName = $"{_tablePrefix}-{SUBCRIPTION_TABLE}", Key = new Dictionary @@ -432,11 +432,11 @@ public async Task SetSubscriptionToken(string eventSubscriptionId, string }, UpdateExpression = "SET external_token = :external_token, external_worker_id = :external_worker_id, external_token_expiry = :external_token_expiry", ConditionExpression = "attribute_not_exists(external_token)", - ExpressionAttributeValues = new Dictionary() + ExpressionAttributeValues = new Dictionary { - { ":external_token" , new AttributeValue() { S = token } }, - { ":external_worker_id" , new AttributeValue() { S = workerId } }, - { ":external_token_expiry" , new AttributeValue() { N = expiry.Ticks.ToString() } } + { ":external_token" , new AttributeValue { S = token } }, + { ":external_worker_id" , new AttributeValue { S = workerId } }, + { ":external_token_expiry" , new AttributeValue { N = expiry.Ticks.ToString() } } } }; try @@ -452,7 +452,7 @@ public async Task SetSubscriptionToken(string eventSubscriptionId, string public async Task ClearSubscriptionToken(string eventSubscriptionId, string token) { - var request = new UpdateItemRequest() + var request = new UpdateItemRequest { TableName = $"{_tablePrefix}-{SUBCRIPTION_TABLE}", Key = new Dictionary @@ -461,9 +461,9 @@ public async Task ClearSubscriptionToken(string eventSubscriptionId, string toke }, UpdateExpression = "REMOVE external_token, external_worker_id, external_token_expiry", ConditionExpression = "external_token = :external_token", - ExpressionAttributeValues = new Dictionary() + ExpressionAttributeValues = new Dictionary { - { ":external_token" , new AttributeValue() { S = token } }, + { ":external_token" , new AttributeValue { S = token } }, } }; diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisProvider.cs index 7db21aab7..5b0830ce0 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisProvider.cs @@ -46,7 +46,7 @@ public async Task PublishNotification(LifeCycleEvent evt) _serializer.Serialize(writer, evt); writer.Flush(); - var response = await _client.PutRecordAsync(new PutRecordRequest() + var response = await _client.PutRecordAsync(new PutRecordRequest { StreamName = _streamName, PartitionKey = evt.WorkflowInstanceId, @@ -93,7 +93,7 @@ private async Task EnsureStream() { try { - await _client.DescribeStreamSummaryAsync(new DescribeStreamSummaryRequest() + await _client.DescribeStreamSummaryAsync(new DescribeStreamSummaryRequest { StreamName = _streamName }); @@ -106,7 +106,7 @@ await _client.DescribeStreamSummaryAsync(new DescribeStreamSummaryRequest() private async Task CreateStream() { - await _client.CreateStreamAsync(new CreateStreamRequest() + await _client.CreateStreamAsync(new CreateStreamRequest { StreamName = _streamName, ShardCount = _defaultShardCount @@ -117,7 +117,7 @@ await _client.CreateStreamAsync(new CreateStreamRequest() { i++; await Task.Delay(3000); - var poll = await _client.DescribeStreamSummaryAsync(new DescribeStreamSummaryRequest() + var poll = await _client.DescribeStreamSummaryAsync(new DescribeStreamSummaryRequest { StreamName = _streamName }); diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisStreamConsumer.cs b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisStreamConsumer.cs index 2a3a42494..799125a0d 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisStreamConsumer.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisStreamConsumer.cs @@ -38,14 +38,14 @@ public KinesisStreamConsumer(AWSCredentials credentials, RegionEndpoint region, public async Task Subscribe(string appName, string stream, Action action) { - var shards = await _client.ListShardsAsync(new ListShardsRequest() + var shards = await _client.ListShardsAsync(new ListShardsRequest { StreamName = stream }); foreach (var shard in shards.Shards) { - _subscribers.Add(new ShardSubscription() + _subscribers.Add(new ShardSubscription { AppName = appName, Stream = stream, @@ -117,7 +117,7 @@ private async Task GetBatch(ShardSubscription sub) if (iterator == null) { - var iterResp = await _client.GetShardIteratorAsync(new GetShardIteratorRequest() + var iterResp = await _client.GetShardIteratorAsync(new GetShardIteratorRequest { ShardId = sub.Shard.ShardId, StreamName = sub.Stream, @@ -129,7 +129,7 @@ private async Task GetBatch(ShardSubscription sub) try { - var result = await _client.GetRecordsAsync(new GetRecordsRequest() + var result = await _client.GetRecordsAsync(new GetRecordsRequest { ShardIterator = iterator, Limit = _batchSize @@ -140,7 +140,7 @@ private async Task GetBatch(ShardSubscription sub) catch (ExpiredIteratorException) { var lastSequence = await _tracker.GetNextLastSequenceNumber(sub.AppName, sub.Stream, sub.Shard.ShardId); - var iterResp = await _client.GetShardIteratorAsync(new GetShardIteratorRequest() + var iterResp = await _client.GetShardIteratorAsync(new GetShardIteratorRequest { ShardId = sub.Shard.ShardId, StreamName = sub.Stream, @@ -149,7 +149,7 @@ private async Task GetBatch(ShardSubscription sub) }); iterator = iterResp.ShardIterator; - var result = await _client.GetRecordsAsync(new GetRecordsRequest() + var result = await _client.GetRecordsAsync(new GetRecordsRequest { ShardIterator = iterator, Limit = _batchSize diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisTracker.cs b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisTracker.cs index 5f4abc2e1..8d6a04b8e 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisTracker.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisTracker.cs @@ -31,7 +31,7 @@ public async Task GetNextShardIterator(string app, string stream, string if (!_tableConfirmed) await EnsureTable(); - var response = await _client.GetItemAsync(new GetItemRequest() + var response = await _client.GetItemAsync(new GetItemRequest { TableName = _tableName, Key = new Dictionary @@ -51,7 +51,7 @@ public async Task GetNextLastSequenceNumber(string app, string stream, s if (!_tableConfirmed) await EnsureTable(); - var response = await _client.GetItemAsync(new GetItemRequest() + var response = await _client.GetItemAsync(new GetItemRequest { TableName = _tableName, Key = new Dictionary @@ -71,7 +71,7 @@ public async Task IncrementShardIterator(string app, string stream, string shard if (!_tableConfirmed) await EnsureTable(); - await _client.UpdateItemAsync(new UpdateItemRequest() + await _client.UpdateItemAsync(new UpdateItemRequest { TableName = _tableName, Key = new Dictionary @@ -79,7 +79,7 @@ await _client.UpdateItemAsync(new UpdateItemRequest() {"id", new AttributeValue(FormatId(app, stream, shard))} }, UpdateExpression = "SET next_iterator = :n", - ExpressionAttributeValues = new Dictionary() + ExpressionAttributeValues = new Dictionary { { ":n" , new AttributeValue(iterator) } } @@ -91,7 +91,7 @@ public async Task IncrementShardIteratorAndSequence(string app, string stream, s if (!_tableConfirmed) await EnsureTable(); - await _client.PutItemAsync(new PutItemRequest() + await _client.PutItemAsync(new PutItemRequest { TableName = _tableName, Item = new Dictionary @@ -118,12 +118,12 @@ private async Task EnsureTable() private async Task CreateTable() { - var createRequest = new CreateTableRequest(_tableName, new List() + var createRequest = new CreateTableRequest(_tableName, new List { new KeySchemaElement("id", KeyType.HASH) }) { - AttributeDefinitions = new List() + AttributeDefinitions = new List { new AttributeDefinition("id", ScalarAttributeType.S) }, diff --git a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedEvent.cs b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedEvent.cs index 341f7b71b..85579f7fc 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedEvent.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedEvent.cs @@ -19,11 +19,11 @@ public class PersistedEvent public bool IsProcessed { get; set; } - private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; + private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; public static PersistedEvent FromInstance(Event instance) { - return new PersistedEvent() + return new PersistedEvent { id = instance.Id, EventKey = instance.EventKey, @@ -36,7 +36,7 @@ public static PersistedEvent FromInstance(Event instance) public static Event ToInstance(PersistedEvent instance) { - return new Event() + return new Event { Id = instance.id, EventKey = instance.EventKey, diff --git a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedSubscription.cs b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedSubscription.cs index d0660046c..55482e17d 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedSubscription.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedSubscription.cs @@ -29,11 +29,11 @@ public class PersistedSubscription public DateTime? ExternalTokenExpiry { get; set; } - private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; + private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; public static PersistedSubscription FromInstance(EventSubscription instance) { - return new PersistedSubscription() + return new PersistedSubscription { id = instance.Id, EventKey = instance.EventKey, @@ -51,7 +51,7 @@ public static PersistedSubscription FromInstance(EventSubscription instance) public static EventSubscription ToInstance(PersistedSubscription instance) { - return new EventSubscription() + return new EventSubscription { Id = instance.id, EventKey = instance.EventKey, diff --git a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedWorkflow.cs b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedWorkflow.cs index c9f565592..bd480fb71 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedWorkflow.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedWorkflow.cs @@ -29,11 +29,11 @@ public class PersistedWorkflow public DateTime? CompleteTime { get; set; } - private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; + private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; public static PersistedWorkflow FromInstance(WorkflowInstance instance) { - var result = new PersistedWorkflow() + var result = new PersistedWorkflow { id = instance.Id, CompleteTime = instance.CompleteTime, @@ -53,7 +53,7 @@ public static PersistedWorkflow FromInstance(WorkflowInstance instance) public static WorkflowInstance ToInstance(PersistedWorkflow instance) { - var result = new WorkflowInstance() + var result = new WorkflowInstance { Id = instance.id, CompleteTime = instance.CompleteTime, diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs index 001ade0a0..ff1c2e187 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs @@ -21,8 +21,8 @@ public async Task Provision(string dbId) { var dbResp = await _client.CreateDatabaseIfNotExistsAsync(dbId); var wfIndexPolicy = new IndexingPolicy(); - wfIndexPolicy.IncludedPaths.Add(new IncludedPath() { Path = @"/*" }); - wfIndexPolicy.ExcludedPaths.Add(new ExcludedPath() { Path = @"/ExecutionPointers/?" }); + wfIndexPolicy.IncludedPaths.Add(new IncludedPath { Path = @"/*" }); + wfIndexPolicy.ExcludedPaths.Add(new ExcludedPath { Path = @"/ExecutionPointers/?" }); Task.WaitAll( dbResp.Database.CreateContainerIfNotExistsAsync(new ContainerProperties(CosmosDbPersistenceProvider.WorkflowContainerName, @"/id") diff --git a/src/providers/WorkflowCore.Providers.Elasticsearch/Models/WorkflowSearchModel.cs b/src/providers/WorkflowCore.Providers.Elasticsearch/Models/WorkflowSearchModel.cs index 91c4838f7..1399bdd23 100644 --- a/src/providers/WorkflowCore.Providers.Elasticsearch/Models/WorkflowSearchModel.cs +++ b/src/providers/WorkflowCore.Providers.Elasticsearch/Models/WorkflowSearchModel.cs @@ -39,7 +39,7 @@ public class WorkflowSearchModel public WorkflowSearchResult ToSearchResult() { - var result = new WorkflowSearchResult() + var result = new WorkflowSearchResult { Id = Id, CompleteTime = CompleteTime, @@ -88,7 +88,7 @@ public static WorkflowSearchModel FromWorkflowInstance(WorkflowInstance workflow { if (ep.Status == PointerStatus.Sleeping) { - result.SleepingSteps.Add(new StepInfo() + result.SleepingSteps.Add(new StepInfo { StepId = ep.StepId, Name = ep.StepName @@ -97,7 +97,7 @@ public static WorkflowSearchModel FromWorkflowInstance(WorkflowInstance workflow if (ep.Status == PointerStatus.WaitingForEvent) { - result.WaitingSteps.Add(new StepInfo() + result.WaitingSteps.Add(new StepInfo { StepId = ep.StepId, Name = ep.StepName @@ -106,7 +106,7 @@ public static WorkflowSearchModel FromWorkflowInstance(WorkflowInstance workflow if (ep.Status == PointerStatus.Failed) { - result.FailedSteps.Add(new StepInfo() + result.FailedSteps.Add(new StepInfo { StepId = ep.StepId, Name = ep.StepName diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisLifeCycleEventHub.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisLifeCycleEventHub.cs index 8d7d1e35d..2cf12e1cc 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisLifeCycleEventHub.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisLifeCycleEventHub.cs @@ -16,7 +16,7 @@ public class RedisLifeCycleEventHub : ILifeCycleEventHub private readonly string _connectionString; private readonly string _channel; private ICollection> _subscribers = new HashSet>(); - private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; + private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; private IConnectionMultiplexer _multiplexer; private ISubscriber _subscriber; diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisLockProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisLockProvider.cs index 1b18e7539..006f531d6 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisLockProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisLockProvider.cs @@ -70,7 +70,7 @@ public Task ReleaseLock(string Id) public async Task Start() { _multiplexer = await ConnectionMultiplexer.ConnectAsync(_connectionString); - _redlockFactory = RedLockFactory.Create(new List() { new RedLockMultiplexer(_multiplexer) }); + _redlockFactory = RedLockFactory.Create(new List { new RedLockMultiplexer(_multiplexer) }); } public async Task Stop() diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs index 3e593a550..66ca58d72 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs @@ -24,7 +24,7 @@ public class RedisPersistenceProvider : IPersistenceProvider private readonly IConnectionMultiplexer _multiplexer; private readonly IDatabase _redis; - private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; + private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; private readonly bool _removeComplete; public RedisPersistenceProvider(string connectionString, string prefix, bool removeComplete, ILoggerFactory logFactory) diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisQueueProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisQueueProvider.cs index dbed9fa98..1281bfbdf 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisQueueProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisQueueProvider.cs @@ -18,7 +18,7 @@ public class RedisQueueProvider : IQueueProvider private IConnectionMultiplexer _multiplexer; private IDatabase _redis; - private readonly Dictionary _queues = new Dictionary() + private readonly Dictionary _queues = new Dictionary { [QueueType.Workflow] = "workflows", [QueueType.Event] = "events", diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs index d9ec3bbeb..8a84f99c6 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs @@ -22,7 +22,7 @@ public class RabbitMQProvider : IQueueProvider private readonly IServiceProvider _serviceProvider; private IConnection _connection = null; - private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; + private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; public bool IsDequeueBlocking => false; diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.QueueProviders.SqlServer/ServiceCollectionExtensions.cs index 7e2364408..ada9b580a 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/ServiceCollectionExtensions.cs @@ -26,7 +26,7 @@ public static WorkflowOptions UseSqlServerBroker(this WorkflowOptions options, s options.Services.AddTransient(); options.Services.AddTransient(sp => new SqlServerQueueProviderMigrator(connectionString, sp.GetService(), sp.GetService())); - var sqlOptions = new SqlServerQueueProviderOptions() + var sqlOptions = new SqlServerQueueProviderOptions { ConnectionString = connectionString, CanCreateDb = canCreateDb, diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/QueueConfigProvider.cs b/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/QueueConfigProvider.cs index 691e6561b..9e54393a1 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/QueueConfigProvider.cs +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/QueueConfigProvider.cs @@ -17,7 +17,7 @@ namespace WorkflowCore.QueueProviders.SqlServer.Services /// public class QueueConfigProvider : IQueueConfigProvider { - private readonly Dictionary _queues = new Dictionary() + private readonly Dictionary _queues = new Dictionary { [QueueType.Workflow] = new QueueConfig("workflow"), [QueueType.Event] = new QueueConfig("event"), diff --git a/src/samples/WorkflowCore.Sample09/ForEachWorkflow.cs b/src/samples/WorkflowCore.Sample09/ForEachWorkflow.cs index 4e525c3de..e9a5cd937 100644 --- a/src/samples/WorkflowCore.Sample09/ForEachWorkflow.cs +++ b/src/samples/WorkflowCore.Sample09/ForEachWorkflow.cs @@ -15,7 +15,7 @@ public void Build(IWorkflowBuilder builder) { builder .StartWith() - .ForEach(data => new List() { 1, 2, 3, 4 }) + .ForEach(data => new List { 1, 2, 3, 4 }) .Do(x => x .StartWith() .Input(step => step.Item, (data, context) => context.Item) diff --git a/src/samples/WorkflowCore.Sample09s/ForEachSyncWorkflow.cs b/src/samples/WorkflowCore.Sample09s/ForEachSyncWorkflow.cs index 685b69ed1..879156d06 100644 --- a/src/samples/WorkflowCore.Sample09s/ForEachSyncWorkflow.cs +++ b/src/samples/WorkflowCore.Sample09s/ForEachSyncWorkflow.cs @@ -15,7 +15,7 @@ public void Build(IWorkflowBuilder builder) { builder .StartWith() - .ForEach(data => new List() { 1, 2, 3, 4 }, data => false) + .ForEach(data => new List { 1, 2, 3, 4 }, data => false) .Do(x => x .StartWith() .Input(step => step.Item, (data, context) => context.Item) diff --git a/src/samples/WorkflowCore.Sample10/Program.cs b/src/samples/WorkflowCore.Sample10/Program.cs index 75173f70c..aa401baa2 100644 --- a/src/samples/WorkflowCore.Sample10/Program.cs +++ b/src/samples/WorkflowCore.Sample10/Program.cs @@ -17,7 +17,7 @@ public static void Main(string[] args) host.Start(); Console.WriteLine("Starting workflow..."); - string workflowId = host.StartWorkflow("While", new MyData() { Counter = 0 }).Result; + string workflowId = host.StartWorkflow("While", new MyData { Counter = 0 }).Result; Console.ReadLine(); diff --git a/src/samples/WorkflowCore.Sample11/Program.cs b/src/samples/WorkflowCore.Sample11/Program.cs index f16853aa4..e409b400a 100644 --- a/src/samples/WorkflowCore.Sample11/Program.cs +++ b/src/samples/WorkflowCore.Sample11/Program.cs @@ -17,7 +17,7 @@ public static void Main(string[] args) host.Start(); Console.WriteLine("Starting workflow..."); - string workflowId = host.StartWorkflow("if-sample", new MyData() { Counter = 4 }).Result; + string workflowId = host.StartWorkflow("if-sample", new MyData { Counter = 4 }).Result; Console.ReadLine(); host.Stop(); diff --git a/src/samples/WorkflowCore.Sample12/Program.cs b/src/samples/WorkflowCore.Sample12/Program.cs index 81f50021d..937265e4f 100644 --- a/src/samples/WorkflowCore.Sample12/Program.cs +++ b/src/samples/WorkflowCore.Sample12/Program.cs @@ -17,7 +17,7 @@ public static void Main(string[] args) host.Start(); Console.WriteLine("Starting workflow..."); - host.StartWorkflow("outcome-sample", new MyData() { Value = 2 }); + host.StartWorkflow("outcome-sample", new MyData { Value = 2 }); Console.ReadLine(); diff --git a/src/samples/WorkflowCore.Sample18/Program.cs b/src/samples/WorkflowCore.Sample18/Program.cs index 8bf555690..295701499 100644 --- a/src/samples/WorkflowCore.Sample18/Program.cs +++ b/src/samples/WorkflowCore.Sample18/Program.cs @@ -20,7 +20,7 @@ static void Main(string[] args) Console.WriteLine("Starting workflow..."); - var workflowId = host.StartWorkflow("activity-sample", new MyData() { Request = "Spend $1,000,000" }).Result; + var workflowId = host.StartWorkflow("activity-sample", new MyData { Request = "Spend $1,000,000" }).Result; var approval = host.GetPendingActivity("get-approval", "worker1", TimeSpan.FromMinutes(1)).Result; diff --git a/src/samples/WorkflowCore.TestSample01/NUnitTest.cs b/src/samples/WorkflowCore.TestSample01/NUnitTest.cs index cec26fe9e..d01aaf5cb 100644 --- a/src/samples/WorkflowCore.TestSample01/NUnitTest.cs +++ b/src/samples/WorkflowCore.TestSample01/NUnitTest.cs @@ -21,7 +21,7 @@ protected override void Setup(bool registerClassMap = false) [Test] public void NUnit_workflow_test_sample() { - var workflowId = StartWorkflow(new MyDataClass() { Value1 = 2, Value2 = 3 }); + var workflowId = StartWorkflow(new MyDataClass { Value1 = 2, Value2 = 3 }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); diff --git a/src/samples/WorkflowCore.TestSample01/xUnitTest.cs b/src/samples/WorkflowCore.TestSample01/xUnitTest.cs index 6aeca8cdc..7afb636f0 100644 --- a/src/samples/WorkflowCore.TestSample01/xUnitTest.cs +++ b/src/samples/WorkflowCore.TestSample01/xUnitTest.cs @@ -17,7 +17,7 @@ public xUnitTest() [Fact] public void MyWorkflow() { - var workflowId = StartWorkflow(new MyDataClass() { Value1 = 2, Value2 = 3 }); + var workflowId = StartWorkflow(new MyDataClass { Value1 = 2, Value2 = 3 }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); diff --git a/test/Docker.Testify/DockerSetup.cs b/test/Docker.Testify/DockerSetup.cs index 7d5ae9bc3..1f6b48b07 100644 --- a/test/Docker.Testify/DockerSetup.cs +++ b/test/Docker.Testify/DockerSetup.cs @@ -60,7 +60,7 @@ public async Task StartContainer() await PullImage(ImageName, ImageTag); - var container = await docker.Containers.CreateContainerAsync(new CreateContainerParameters() + var container = await docker.Containers.CreateContainerAsync(new CreateContainerParameters { Image = $"{ImageName}:{ImageTag}", Name = $"{ContainerPrefix}-{Guid.NewGuid()}", @@ -113,13 +113,13 @@ public async Task PullImage(string name, string tag) return; Debug.WriteLine($"Pulling docker image {name}:{tag}"); - await docker.Images.CreateImageAsync(new ImagesCreateParameters() { FromImage = name, Tag = tag }, null, new Progress()); + await docker.Images.CreateImageAsync(new ImagesCreateParameters { FromImage = name, Tag = tag }, null, new Progress()); } public void Dispose() { docker.Containers.KillContainerAsync(containerId, new ContainerKillParameters()).Wait(); - docker.Containers.RemoveContainerAsync(containerId, new ContainerRemoveParameters() { Force = true }).Wait(); + docker.Containers.RemoveContainerAsync(containerId, new ContainerRemoveParameters { Force = true }).Wait(); } private int GetFreePort() diff --git a/test/ScratchPad/ElasticTest.cs b/test/ScratchPad/ElasticTest.cs index 0e57c4012..6d8ae43f0 100644 --- a/test/ScratchPad/ElasticTest.cs +++ b/test/ScratchPad/ElasticTest.cs @@ -30,10 +30,10 @@ public static void test(string[] args) host.RegisterWorkflow(); host.Start(); - var data1 = new WorkflowCore.Sample03.MyDataClass() { Value1 = 2, Value2 = 3 }; + var data1 = new WorkflowCore.Sample03.MyDataClass { Value1 = 2, Value2 = 3 }; host.StartWorkflow("PassingDataWorkflow", data1, "quick dog").Wait(); - var data2 = new WorkflowCore.Sample04.MyDataClass() { Value1 = "test" }; + var data2 = new WorkflowCore.Sample04.MyDataClass { Value1 = "test" }; host.StartWorkflow("EventSampleWorkflow", data2, "alt1 boom").Wait(); diff --git a/test/ScratchPad/Program.cs b/test/ScratchPad/Program.cs index 08f383712..3c0ee5f76 100644 --- a/test/ScratchPad/Program.cs +++ b/test/ScratchPad/Program.cs @@ -40,7 +40,7 @@ public static void Main(string[] args) for (var i = 0; i < 12000; i++) { - var wid = host.StartWorkflow("Test01", 1, new WfData() { Value1 = "two", Value2 = "data2" }).Result; + var wid = host.StartWorkflow("Test01", 1, new WfData { Value1 = "two", Value2 = "data2" }).Result; ids.Add(wid); } diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs index 03562bfbd..ae7b372ab 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs @@ -51,13 +51,13 @@ public ActivityScenario() [Fact] public void Scenario() { - var workflowId = StartWorkflow(new MyDataClass() { ActivityInput = new ActivityInput() { Value1 = "a", Value2 = 1 } }); + var workflowId = StartWorkflow(new MyDataClass { ActivityInput = new ActivityInput { Value1 = "a", Value2 = 1 } }); var activity = Host.GetPendingActivity("act-1", "worker1", TimeSpan.FromSeconds(30)).Result; if (activity != null) { var actInput = (ActivityInput)activity.Parameters; - Host.SubmitActivitySuccess(activity.Token, new ActivityOutput() + Host.SubmitActivitySuccess(activity.Token, new ActivityOutput { Value1 = actInput.Value1 + "1", Value2 = actInput.Value2 + 1 diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario.cs index 55c336020..a07d1e44a 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario.cs @@ -54,7 +54,7 @@ public CompensationScenario() [Fact] public void NoExceptionScenario() { - var workflowId = StartWorkflow(new MyDataClass() { ThrowException = false }); + var workflowId = StartWorkflow(new MyDataClass { ThrowException = false }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); @@ -68,7 +68,7 @@ public void NoExceptionScenario() [Fact] public void ExceptionScenario() { - var workflowId = StartWorkflow(new MyDataClass() { ThrowException = true }); + var workflowId = StartWorkflow(new MyDataClass { ThrowException = true }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario2.cs b/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario2.cs index 2b2000304..d27564f07 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario2.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario2.cs @@ -59,7 +59,7 @@ public CompensationScenario2() [Fact] public void NoExceptionScenario() { - var workflowId = StartWorkflow(new MyDataClass() { ThrowException = false }); + var workflowId = StartWorkflow(new MyDataClass { ThrowException = false }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); @@ -74,7 +74,7 @@ public void NoExceptionScenario() [Fact] public void ExceptionScenario() { - var workflowId = StartWorkflow(new MyDataClass() { ThrowException = true }); + var workflowId = StartWorkflow(new MyDataClass { ThrowException = true }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs index 0e460defd..d5adab795 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs @@ -62,7 +62,7 @@ public DataIOScenario() public void Scenario() { decimal v4 = 1.235465673450897890m; - var workflowId = StartWorkflow(new MyDataClass() {Value1 = 2, Value2 = 3, Value4 = v4, SubValue = new DataSubclass() {Value5 = v4}}); + var workflowId = StartWorkflow(new MyDataClass {Value1 = 2, Value2 = 3, Value4 = v4, SubValue = new DataSubclass {Value5 = v4}}); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/DecisionScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/DecisionScenario.cs index 3ae1faa66..4d9f733fd 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/DecisionScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/DecisionScenario.cs @@ -78,7 +78,7 @@ public DecisionScenario() [Fact] public void Scenario1() { - var workflowId = StartWorkflow(new MyDataClass() { Op = "+", Value1 = 2, Value2 = 3 }); + var workflowId = StartWorkflow(new MyDataClass { Op = "+", Value1 = 2, Value2 = 3 }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); @@ -89,7 +89,7 @@ public void Scenario1() [Fact] public void Scenario2() { - var workflowId = StartWorkflow(new MyDataClass() { Op = "-", Value1 = 2, Value2 = 3 }); + var workflowId = StartWorkflow(new MyDataClass { Op = "-", Value1 = 2, Value2 = 3 }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/DynamicDataIOScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/DynamicDataIOScenario.cs index 416db55f2..aa6591f6a 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/DynamicDataIOScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/DynamicDataIOScenario.cs @@ -58,7 +58,7 @@ public DynamicDataIOScenario() [Fact] public void Scenario() { - var workflowId = StartWorkflow(new MyDataClass() { Value1 = 2, Value2 = 3 }); + var workflowId = StartWorkflow(new MyDataClass { Value1 = 2, Value2 = 3 }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/EventScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/EventScenario.cs index 86a6703df..7d5fd2dea 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/EventScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/EventScenario.cs @@ -42,7 +42,7 @@ public EventScenario() public void Scenario() { var eventKey = Guid.NewGuid().ToString(); - var workflowId = StartWorkflow(new MyDataClass() { StrValue1 = eventKey, StrValue2 = eventKey }); + var workflowId = StartWorkflow(new MyDataClass { StrValue1 = eventKey, StrValue2 = eventKey }); WaitForEventSubscription("MyEvent", eventKey, TimeSpan.FromSeconds(30)); Host.PublishEvent("MyEvent", eventKey, "Pass1"); WaitForEventSubscription("MyEvent2", eventKey, TimeSpan.FromSeconds(30)); diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ForeachScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ForeachScenario.cs index f10c8ee01..f16c89b24 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/ForeachScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ForeachScenario.cs @@ -44,7 +44,7 @@ public void Build(IWorkflowBuilder builder) Step1Ticker++; return ExecutionResult.Next(); }) - .ForEach(x => new List() { 2, 2, 3 }) + .ForEach(x => new List { 2, 2, 3 }) .Do(x => x.StartWith()) .Then(context => { diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ForeachSyncScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ForeachSyncScenario.cs index 61cf3484c..74e29fd3a 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/ForeachSyncScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ForeachSyncScenario.cs @@ -34,7 +34,7 @@ public void Build(IWorkflowBuilder builder) { builder .StartWith(_ => ExecutionResult.Next()) - .ForEach(x => new List() { 10, 2, 3 }, _ => false) + .ForEach(x => new List { 10, 2, 3 }, _ => false) .Do(x => x .StartWith() .Input(step => step.Period, (_, context) => TimeSpan.FromSeconds((int)context.Item)) diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/IfScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/IfScenario.cs index f7e0e7817..bd2c9808a 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/IfScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/IfScenario.cs @@ -78,7 +78,7 @@ public IfScenario() [Fact] public void Scenario() { - var workflowId = StartWorkflow(new MyDataClass() { Counter = 2 }); + var workflowId = StartWorkflow(new MyDataClass { Counter = 2 }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); Step1Ticker.Should().Be(1); diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/SagaScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/SagaScenario.cs index fea1e4402..bfa935ef7 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/SagaScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/SagaScenario.cs @@ -75,7 +75,7 @@ public SagaScenario() [Fact] public void NoExceptionScenario() { - var workflowId = StartWorkflow(new MyDataClass() { ThrowException = false }); + var workflowId = StartWorkflow(new MyDataClass { ThrowException = false }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); @@ -95,7 +95,7 @@ public void NoExceptionScenario() [Fact] public void ExceptionScenario() { - var workflowId = StartWorkflow(new MyDataClass() { ThrowException = true }); + var workflowId = StartWorkflow(new MyDataClass { ThrowException = true }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs index 7d8a0117a..eb51107b8 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs @@ -21,7 +21,7 @@ public StoredJsonScenario() [Fact(DisplayName = "Execute branch 1")] public void should_execute_branch1() { - var workflowId = StartWorkflow(TestAssets.Utils.GetTestDefinitionJson(), new CounterBoard() { Flag1 = true, Flag2 = true, Flag3 = true }); + var workflowId = StartWorkflow(TestAssets.Utils.GetTestDefinitionJson(), new CounterBoard { Flag1 = true, Flag2 = true, Flag3 = true }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); var data = GetData(workflowId); @@ -40,7 +40,7 @@ public void should_execute_branch1() [Fact(DisplayName = "Execute branch 2")] public void should_execute_branch2() { - var workflowId = StartWorkflow(TestAssets.Utils.GetTestDefinitionJson(), new CounterBoard() { Flag1 = true, Flag2 = true, Flag3 = false }); + var workflowId = StartWorkflow(TestAssets.Utils.GetTestDefinitionJson(), new CounterBoard { Flag1 = true, Flag2 = true, Flag3 = false }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); var data = GetData(workflowId); diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs index 3b37d2eb7..26b1f687a 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs @@ -21,7 +21,7 @@ public StoredYamlScenario() [Fact(DisplayName = "Execute workflow from stored YAML definition")] public void should_execute_yaml_workflow() { - var workflowId = StartWorkflow(TestAssets.Utils.GetTestDefinitionYaml(), new CounterBoard() { Flag1 = true, Flag2 = true }); + var workflowId = StartWorkflow(TestAssets.Utils.GetTestDefinitionYaml(), new CounterBoard { Flag1 = true, Flag2 = true }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); var data = GetData(workflowId); diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/WhenScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/WhenScenario.cs index 95103dc63..7d7095e6c 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/WhenScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/WhenScenario.cs @@ -71,7 +71,7 @@ public WhenScenario() [Fact] public void Scenario() { - var workflowId = StartWorkflow(new MyDataClass() { Counter = 2 }); + var workflowId = StartWorkflow(new MyDataClass { Counter = 2 }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); Case1Ticker.Should().Be(0); diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/WhileScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/WhileScenario.cs index 67d364ced..5ca2cd20a 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/WhileScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/WhileScenario.cs @@ -69,7 +69,7 @@ public WhileScenario() [Fact] public void Scenario() { - var workflowId = StartWorkflow(new MyDataClass() { Counter = 0 }); + var workflowId = StartWorkflow(new MyDataClass { Counter = 0 }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); Step1Ticker.Should().Be(1); diff --git a/test/WorkflowCore.IntegrationTests/SearchIndexTests.cs b/test/WorkflowCore.IntegrationTests/SearchIndexTests.cs index d244ff7c3..091dafe22 100644 --- a/test/WorkflowCore.IntegrationTests/SearchIndexTests.cs +++ b/test/WorkflowCore.IntegrationTests/SearchIndexTests.cs @@ -30,7 +30,7 @@ protected IEnumerable BuildTestData() { var result = new List(); - result.Add(new WorkflowInstance() + result.Add(new WorkflowInstance { Id = "1", CreateTime = new DateTime(2010, 1, 1), @@ -38,25 +38,25 @@ protected IEnumerable BuildTestData() Reference = "ref1" }); - result.Add(new WorkflowInstance() + result.Add(new WorkflowInstance { Id = "2", CreateTime = new DateTime(2020, 1, 1), Status = WorkflowStatus.Runnable, Reference = "ref2", - Data = new DataObject() + Data = new DataObject { Value3 = 7 } }); - result.Add(new WorkflowInstance() + result.Add(new WorkflowInstance { Id = "3", CreateTime = new DateTime(2010, 1, 1), Status = WorkflowStatus.Complete, Reference = "ref3", - Data = new DataObject() + Data = new DataObject { Value3 = 5, Value1 = "quick fox", @@ -64,13 +64,13 @@ protected IEnumerable BuildTestData() } }); - result.Add(new WorkflowInstance() + result.Add(new WorkflowInstance { Id = "4", CreateTime = new DateTime(2010, 1, 1), Status = WorkflowStatus.Complete, Reference = "ref4", - Data = new AltDataObject() + Data = new AltDataObject { Value1 = 9, Value2 = new DateTime(2000, 1, 1) @@ -165,7 +165,7 @@ class DataObject : ISearchable public IEnumerable GetSearchTokens() { - return new List() + return new List { Value1, Value2 diff --git a/test/WorkflowCore.TestAssets/Utils.cs b/test/WorkflowCore.TestAssets/Utils.cs index ea0f85f54..48a479b47 100644 --- a/test/WorkflowCore.TestAssets/Utils.cs +++ b/test/WorkflowCore.TestAssets/Utils.cs @@ -9,7 +9,7 @@ namespace WorkflowCore.TestAssets { public static class Utils { - private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All, DateFormatHandling = DateFormatHandling.IsoDateFormat, DateTimeZoneHandling = DateTimeZoneHandling.Utc }; + private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All, DateFormatHandling = DateFormatHandling.IsoDateFormat, DateTimeZoneHandling = DateTimeZoneHandling.Utc }; public static T DeepCopy(T obj) { diff --git a/test/WorkflowCore.Testing/JsonWorkflowTest.cs b/test/WorkflowCore.Testing/JsonWorkflowTest.cs index 760966a52..cfabc7877 100644 --- a/test/WorkflowCore.Testing/JsonWorkflowTest.cs +++ b/test/WorkflowCore.Testing/JsonWorkflowTest.cs @@ -43,7 +43,7 @@ protected virtual void Setup() private void Host_OnStepError(WorkflowInstance workflow, WorkflowStep step, Exception exception) { - UnhandledStepErrors.Add(new StepError() + UnhandledStepErrors.Add(new StepError { Exception = exception, Step = step, diff --git a/test/WorkflowCore.Testing/WorkflowTest.cs b/test/WorkflowCore.Testing/WorkflowTest.cs index 32a1259be..3f8a29ea3 100644 --- a/test/WorkflowCore.Testing/WorkflowTest.cs +++ b/test/WorkflowCore.Testing/WorkflowTest.cs @@ -48,7 +48,7 @@ protected virtual void Setup(bool registerClassMap = false) protected void Host_OnStepError(WorkflowInstance workflow, WorkflowStep step, Exception exception) { - UnhandledStepErrors.Add(new StepError() + UnhandledStepErrors.Add(new StepError { Exception = exception, Step = step, diff --git a/test/WorkflowCore.Testing/YamlWorkflowTest.cs b/test/WorkflowCore.Testing/YamlWorkflowTest.cs index b16d07a6d..a9d180b98 100644 --- a/test/WorkflowCore.Testing/YamlWorkflowTest.cs +++ b/test/WorkflowCore.Testing/YamlWorkflowTest.cs @@ -43,7 +43,7 @@ protected virtual void Setup() private void Host_OnStepError(WorkflowInstance workflow, WorkflowStep step, Exception exception) { - UnhandledStepErrors.Add(new StepError() + UnhandledStepErrors.Add(new StepError { Exception = exception, Step = step, diff --git a/test/WorkflowCore.UnitTests/BasePersistenceFixture.cs b/test/WorkflowCore.UnitTests/BasePersistenceFixture.cs index 87b733a2d..0afa9bd7e 100644 --- a/test/WorkflowCore.UnitTests/BasePersistenceFixture.cs +++ b/test/WorkflowCore.UnitTests/BasePersistenceFixture.cs @@ -17,7 +17,7 @@ public abstract class BasePersistenceFixture [Fact] public void CreateNewWorkflow_should_generate_id() { - var workflow = new WorkflowInstance() + var workflow = new WorkflowInstance { Data = new { Value1 = 7 }, Description = "My Description", @@ -26,7 +26,7 @@ public void CreateNewWorkflow_should_generate_id() Version = 1, WorkflowDefinitionId = "My Workflow" }; - workflow.ExecutionPointers.Add(new ExecutionPointer() + workflow.ExecutionPointers.Add(new ExecutionPointer { Id = Guid.NewGuid().ToString(), Active = true, @@ -42,9 +42,9 @@ public void CreateNewWorkflow_should_generate_id() [Fact] public void GetWorkflowInstance_should_retrieve_workflow() { - var workflow = new WorkflowInstance() + var workflow = new WorkflowInstance { - Data = new TestData() { Value1 = 7 }, + Data = new TestData { Value1 = 7 }, Description = "My Description", Status = WorkflowStatus.Runnable, NextExecution = 0, @@ -52,13 +52,13 @@ public void GetWorkflowInstance_should_retrieve_workflow() WorkflowDefinitionId = "My Workflow", Reference = "My Reference" }; - workflow.ExecutionPointers.Add(new ExecutionPointer() + workflow.ExecutionPointers.Add(new ExecutionPointer { Id = "1", Active = true, StepId = 0, SleepUntil = new DateTime(2000, 1, 1).ToUniversalTime(), - Scope = new List() { "4", "3", "2", "1" } + Scope = new List { "4", "3", "2", "1" } }); var workflowId = Subject.CreateNewWorkflow(workflow).Result; @@ -72,9 +72,9 @@ public void GetWorkflowInstance_should_retrieve_workflow() [Fact] public void GetWorkflowInstances_should_retrieve_workflows() { - var workflow01 = new WorkflowInstance() + var workflow01 = new WorkflowInstance { - Data = new TestData() { Value1 = 7 }, + Data = new TestData { Value1 = 7 }, Description = "My Description", Status = WorkflowStatus.Runnable, NextExecution = 0, @@ -82,19 +82,19 @@ public void GetWorkflowInstances_should_retrieve_workflows() WorkflowDefinitionId = "My Workflow", Reference = "My Reference" }; - workflow01.ExecutionPointers.Add(new ExecutionPointer() + workflow01.ExecutionPointers.Add(new ExecutionPointer { Id = "1", Active = true, StepId = 0, SleepUntil = new DateTime(2000, 1, 1).ToUniversalTime(), - Scope = new List() { "4", "3", "2", "1" } + Scope = new List { "4", "3", "2", "1" } }); var workflowId01 = Subject.CreateNewWorkflow(workflow01).Result; - var workflow02 = new WorkflowInstance() + var workflow02 = new WorkflowInstance { - Data = new TestData() { Value1 = 7 }, + Data = new TestData { Value1 = 7 }, Description = "My Description", Status = WorkflowStatus.Runnable, NextExecution = 0, @@ -102,19 +102,19 @@ public void GetWorkflowInstances_should_retrieve_workflows() WorkflowDefinitionId = "My Workflow", Reference = "My Reference" }; - workflow02.ExecutionPointers.Add(new ExecutionPointer() + workflow02.ExecutionPointers.Add(new ExecutionPointer { Id = "1", Active = true, StepId = 0, SleepUntil = new DateTime(2000, 1, 1).ToUniversalTime(), - Scope = new List() { "4", "3", "2", "1" } + Scope = new List { "4", "3", "2", "1" } }); var workflowId02 = Subject.CreateNewWorkflow(workflow02).Result; - var workflow03 = new WorkflowInstance() + var workflow03 = new WorkflowInstance { - Data = new TestData() { Value1 = 7 }, + Data = new TestData { Value1 = 7 }, Description = "My Description", Status = WorkflowStatus.Runnable, NextExecution = 0, @@ -122,13 +122,13 @@ public void GetWorkflowInstances_should_retrieve_workflows() WorkflowDefinitionId = "My Workflow", Reference = "My Reference" }; - workflow03.ExecutionPointers.Add(new ExecutionPointer() + workflow03.ExecutionPointers.Add(new ExecutionPointer { Id = "1", Active = true, StepId = 0, SleepUntil = new DateTime(2000, 1, 1).ToUniversalTime(), - Scope = new List() { "4", "3", "2", "1" } + Scope = new List { "4", "3", "2", "1" } }); var workflowId03 = Subject.CreateNewWorkflow(workflow03).Result; @@ -155,9 +155,9 @@ public void GetWorkflowInstances_should_retrieve_workflows() [Fact] public void PersistWorkflow() { - var oldWorkflow = new WorkflowInstance() + var oldWorkflow = new WorkflowInstance { - Data = new TestData() { Value1 = 7 }, + Data = new TestData { Value1 = 7 }, Description = "My Description", Status = WorkflowStatus.Runnable, NextExecution = 0, @@ -166,19 +166,19 @@ public void PersistWorkflow() CreateTime = new DateTime(2000, 1, 1).ToUniversalTime(), Reference = "My Reference" }; - oldWorkflow.ExecutionPointers.Add(new ExecutionPointer() + oldWorkflow.ExecutionPointers.Add(new ExecutionPointer { Id = Guid.NewGuid().ToString(), Active = true, StepId = 0, - Scope = new List() { "1", "2", "3", "4" } + Scope = new List { "1", "2", "3", "4" } }); var workflowId = Subject.CreateNewWorkflow(oldWorkflow).Result; var newWorkflow = Utils.DeepCopy(oldWorkflow); newWorkflow.Data = oldWorkflow.Data; newWorkflow.Reference = oldWorkflow.Reference; newWorkflow.NextExecution = 7; - newWorkflow.ExecutionPointers.Add(new ExecutionPointer() { Id = Guid.NewGuid().ToString(), Active = true, StepId = 1 }); + newWorkflow.ExecutionPointers.Add(new ExecutionPointer { Id = Guid.NewGuid().ToString(), Active = true, StepId = 1 }); Subject.PersistWorkflow(newWorkflow).Wait(); @@ -197,9 +197,9 @@ public void ConcurrentPersistWorkflow() { actions.Add(() => { - var oldWorkflow = new WorkflowInstance() + var oldWorkflow = new WorkflowInstance { - Data = new TestData() { Value1 = 7 }, + Data = new TestData { Value1 = 7 }, Description = "My Description", Status = WorkflowStatus.Runnable, NextExecution = 0, @@ -207,7 +207,7 @@ public void ConcurrentPersistWorkflow() WorkflowDefinitionId = "My Workflow", CreateTime = new DateTime(2000, 1, 1).ToUniversalTime() }; - oldWorkflow.ExecutionPointers.Add(new ExecutionPointer() + oldWorkflow.ExecutionPointers.Add(new ExecutionPointer { Id = Guid.NewGuid().ToString(), Active = true, @@ -216,7 +216,7 @@ public void ConcurrentPersistWorkflow() var workflowId = subject.CreateNewWorkflow(oldWorkflow).Result; var newWorkflow = Utils.DeepCopy(oldWorkflow); newWorkflow.NextExecution = 7; - newWorkflow.ExecutionPointers.Add(new ExecutionPointer() { Id = Guid.NewGuid().ToString(), Active = true, StepId = 1 }); + newWorkflow.ExecutionPointers.Add(new ExecutionPointer { Id = Guid.NewGuid().ToString(), Active = true, StepId = 1 }); subject.PersistWorkflow(newWorkflow).Wait(); // It will throw an exception if the persistence provider occurred resource competition. }); diff --git a/test/WorkflowCore.UnitTests/Models/MemberMapParameterTests.cs b/test/WorkflowCore.UnitTests/Models/MemberMapParameterTests.cs index c25b57857..b486d039e 100644 --- a/test/WorkflowCore.UnitTests/Models/MemberMapParameterTests.cs +++ b/test/WorkflowCore.UnitTests/Models/MemberMapParameterTests.cs @@ -18,7 +18,7 @@ public void should_assign_input() Expression> memberExpr = (x => x.Value1); Expression> valueExpr = (x => x.Value1); var subject = new MemberMapParameter(valueExpr, memberExpr); - var data = new MyData() + var data = new MyData { Value1 = 5 }; @@ -36,7 +36,7 @@ public void should_assign_output() Expression> valueExpr = (x => x.Value1); var subject = new MemberMapParameter(valueExpr, memberExpr); var data = new MyData(); - var step = new MyStep() + var step = new MyStep { Value1 = 5 }; @@ -53,7 +53,7 @@ public void should_convert_input() Expression> valueExpr = (x => x.Value1); var subject = new MemberMapParameter(valueExpr, memberExpr); - var data = new MyData() + var data = new MyData { Value1 = 5 }; @@ -72,7 +72,7 @@ public void should_convert_output() Expression> valueExpr = (x => x.Value1); var subject = new MemberMapParameter(valueExpr, memberExpr); - var data = new MyData() + var data = new MyData { Value1 = 5 }; diff --git a/test/WorkflowCore.UnitTests/Services/ExecutionResultProcessorFixture.cs b/test/WorkflowCore.UnitTests/Services/ExecutionResultProcessorFixture.cs index 557abdb5a..f6bc0cf35 100644 --- a/test/WorkflowCore.UnitTests/Services/ExecutionResultProcessorFixture.cs +++ b/test/WorkflowCore.UnitTests/Services/ExecutionResultProcessorFixture.cs @@ -48,15 +48,15 @@ public void should_advance_workflow() { //arrange var definition = new WorkflowDefinition(); - var pointer1 = new ExecutionPointer() { Id = "1", Active = true, StepId = 0, Status = PointerStatus.Running }; - var pointer2 = new ExecutionPointer() { Id = "2" }; - var outcome = new ValueOutcome() { NextStep = 1 }; + var pointer1 = new ExecutionPointer { Id = "1", Active = true, StepId = 0, Status = PointerStatus.Running }; + var pointer2 = new ExecutionPointer { Id = "2" }; + var outcome = new ValueOutcome { NextStep = 1 }; var step = A.Fake(); var workflowResult = new WorkflowExecutorResult(); var instance = GivenWorkflow(pointer1); var result = ExecutionResult.Next(); - A.CallTo(() => step.Outcomes).Returns(new List() { outcome }); + A.CallTo(() => step.Outcomes).Returns(new List { outcome }); A.CallTo(() => PointerFactory.BuildNextPointer(definition, pointer1, outcome)).Returns(pointer2); //act @@ -77,7 +77,7 @@ public void should_set_persistence_data() //arrange var persistenceData = new object(); var definition = new WorkflowDefinition(); - var pointer = new ExecutionPointer() { Id = "1", Active = true, StepId = 0, Status = PointerStatus.Running }; + var pointer = new ExecutionPointer { Id = "1", Active = true, StepId = 0, Status = PointerStatus.Running }; var step = A.Fake(); var workflowResult = new WorkflowExecutorResult(); var instance = GivenWorkflow(pointer); @@ -95,7 +95,7 @@ public void should_subscribe_to_event() { //arrange var definition = new WorkflowDefinition(); - var pointer = new ExecutionPointer() { Id = "1", Active = true, StepId = 0, Status = PointerStatus.Running }; + var pointer = new ExecutionPointer { Id = "1", Active = true, StepId = 0, Status = PointerStatus.Running }; var step = A.Fake(); var workflowResult = new WorkflowExecutorResult(); var instance = GivenWorkflow(pointer); @@ -117,19 +117,19 @@ public void should_select_correct_outcomes() { //arrange var definition = new WorkflowDefinition(); - var pointer1 = new ExecutionPointer() { Id = "1", Active = true, StepId = 0, Status = PointerStatus.Running }; - var pointer2 = new ExecutionPointer() { Id = "2" }; - var pointer3 = new ExecutionPointer() { Id = "3" }; + var pointer1 = new ExecutionPointer { Id = "1", Active = true, StepId = 0, Status = PointerStatus.Running }; + var pointer2 = new ExecutionPointer { Id = "2" }; + var pointer3 = new ExecutionPointer { Id = "3" }; Expression> expr1 = data => 10; Expression> expr2 = data => 20; - var outcome1 = new ValueOutcome() { NextStep = 1, Value = expr1 }; - var outcome2 = new ValueOutcome() { NextStep = 2, Value = expr2 }; + var outcome1 = new ValueOutcome { NextStep = 1, Value = expr1 }; + var outcome2 = new ValueOutcome { NextStep = 2, Value = expr2 }; var step = A.Fake(); var workflowResult = new WorkflowExecutorResult(); var instance = GivenWorkflow(pointer1); var result = ExecutionResult.Outcome(20); - A.CallTo(() => step.Outcomes).Returns(new List() { outcome1, outcome2 }); + A.CallTo(() => step.Outcomes).Returns(new List { outcome1, outcome2 }); A.CallTo(() => PointerFactory.BuildNextPointer(definition, pointer1, outcome1)).Returns(pointer2); A.CallTo(() => PointerFactory.BuildNextPointer(definition, pointer1, outcome2)).Returns(pointer3); @@ -153,7 +153,7 @@ public void should_sleep_pointer() //arrange var persistenceData = new object(); var definition = new WorkflowDefinition(); - var pointer = new ExecutionPointer() { Id = "1", Active = true, StepId = 0, Status = PointerStatus.Running }; + var pointer = new ExecutionPointer { Id = "1", Active = true, StepId = 0, Status = PointerStatus.Running }; var step = A.Fake(); var workflowResult = new WorkflowExecutorResult(); var instance = GivenWorkflow(pointer); @@ -174,14 +174,14 @@ public void should_branch_children() var branch = 10; var child = 2; var definition = new WorkflowDefinition(); - var pointer = new ExecutionPointer() { Id = "1", Active = true, StepId = 0, Status = PointerStatus.Running }; - var childPointer = new ExecutionPointer() { Id = "2" }; + var pointer = new ExecutionPointer { Id = "1", Active = true, StepId = 0, Status = PointerStatus.Running }; + var childPointer = new ExecutionPointer { Id = "2" }; var step = A.Fake(); var workflowResult = new WorkflowExecutorResult(); var instance = GivenWorkflow(pointer); - var result = ExecutionResult.Branch(new List() { branch }, null); + var result = ExecutionResult.Branch(new List { branch }, null); - A.CallTo(() => step.Children).Returns(new List() { child }); + A.CallTo(() => step.Children).Returns(new List { child }); A.CallTo(() => PointerFactory.BuildChildPointer(definition, pointer, child, branch)).Returns(childPointer); //act @@ -197,7 +197,7 @@ private static WorkflowInstance GivenWorkflow(ExecutionPointer pointer) return new WorkflowInstance { Status = WorkflowStatus.Runnable, - ExecutionPointers = new ExecutionPointerCollection(new List() + ExecutionPointers = new ExecutionPointerCollection(new List { pointer }) diff --git a/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs b/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs index cefaf9a23..037dd0e33 100644 --- a/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs +++ b/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs @@ -91,9 +91,9 @@ public void should_execute_active_step() Status = WorkflowStatus.Runnable, NextExecution = 0, Id = "001", - ExecutionPointers = new ExecutionPointerCollection(new List() + ExecutionPointers = new ExecutionPointerCollection(new List { - new ExecutionPointer() { Id = "1", Active = true, StepId = 0 } + new ExecutionPointer { Id = "1", Active = true, StepId = 0 } }) }; @@ -121,9 +121,9 @@ public void should_trigger_step_hooks() Status = WorkflowStatus.Runnable, NextExecution = 0, Id = "001", - ExecutionPointers = new ExecutionPointerCollection(new List() + ExecutionPointers = new ExecutionPointerCollection(new List { - new ExecutionPointer() { Id = "1", Active = true, StepId = 0 } + new ExecutionPointer { Id = "1", Active = true, StepId = 0 } }) }; @@ -152,9 +152,9 @@ public void should_not_execute_inactive_step() Status = WorkflowStatus.Runnable, NextExecution = 0, Id = "001", - ExecutionPointers = new ExecutionPointerCollection(new List() + ExecutionPointers = new ExecutionPointerCollection(new List { - new ExecutionPointer() { Id = "1", Active = false, StepId = 0 } + new ExecutionPointer { Id = "1", Active = false, StepId = 0 } }) }; @@ -173,7 +173,7 @@ public void should_map_inputs() var step1Body = A.Fake(); A.CallTo(() => step1Body.RunAsync(A.Ignored)).Returns(ExecutionResult.Next()); - WorkflowStep step1 = BuildFakeStep(step1Body, new List() + WorkflowStep step1 = BuildFakeStep(step1Body, new List { param } @@ -188,10 +188,10 @@ public void should_map_inputs() Status = WorkflowStatus.Runnable, NextExecution = 0, Id = "001", - Data = new DataClass() { Value1 = 5 }, - ExecutionPointers = new ExecutionPointerCollection(new List() + Data = new DataClass { Value1 = 5 }, + ExecutionPointers = new ExecutionPointerCollection(new List { - new ExecutionPointer() { Id = "1", Active = true, StepId = 0 } + new ExecutionPointer { Id = "1", Active = true, StepId = 0 } }) }; @@ -212,7 +212,7 @@ public void should_map_outputs() var step1Body = A.Fake(); A.CallTo(() => step1Body.Property1).Returns(7); A.CallTo(() => step1Body.RunAsync(A.Ignored)).Returns(ExecutionResult.Next()); - WorkflowStep step1 = BuildFakeStep(step1Body, new List(), new List() + WorkflowStep step1 = BuildFakeStep(step1Body, new List(), new List { param } @@ -220,7 +220,7 @@ public void should_map_outputs() Given1StepWorkflow(step1, "Workflow", 1); - var data = new DataClass() { Value1 = 5 }; + var data = new DataClass { Value1 = 5 }; var instance = new WorkflowInstance { @@ -230,9 +230,9 @@ public void should_map_outputs() NextExecution = 0, Id = "001", Data = data, - ExecutionPointers = new ExecutionPointerCollection(new List() + ExecutionPointers = new ExecutionPointerCollection(new List { - new ExecutionPointer() { Id = "1", Active = true, StepId = 0 } + new ExecutionPointer { Id = "1", Active = true, StepId = 0 } }) }; @@ -262,9 +262,9 @@ public void should_handle_step_exception() Status = WorkflowStatus.Runnable, NextExecution = 0, Id = "001", - ExecutionPointers = new ExecutionPointerCollection(new List() + ExecutionPointers = new ExecutionPointerCollection(new List { - new ExecutionPointer() { Id = "1", Active = true, StepId = 0 } + new ExecutionPointer { Id = "1", Active = true, StepId = 0 } }) }; @@ -293,9 +293,9 @@ public void should_process_after_execution_iteration() Status = WorkflowStatus.Runnable, NextExecution = 0, Id = "001", - ExecutionPointers = new ExecutionPointerCollection(new List() + ExecutionPointers = new ExecutionPointerCollection(new List { - new ExecutionPointer() { Id = "1", Active = true, StepId = 0 } + new ExecutionPointer { Id = "1", Active = true, StepId = 0 } }) }; @@ -322,9 +322,9 @@ public void should_process_cancellations() Status = WorkflowStatus.Runnable, NextExecution = 0, Id = "001", - ExecutionPointers = new ExecutionPointerCollection(new List() + ExecutionPointers = new ExecutionPointerCollection(new List { - new ExecutionPointer() { Id = "1", Active = true, StepId = 0 } + new ExecutionPointer { Id = "1", Active = true, StepId = 0 } }) }; @@ -338,12 +338,12 @@ public void should_process_cancellations() private void Given1StepWorkflow(WorkflowStep step1, string id, int version) { - A.CallTo(() => Registry.GetDefinition(id, version)).Returns(new WorkflowDefinition() + A.CallTo(() => Registry.GetDefinition(id, version)).Returns(new WorkflowDefinition { Id = id, Version = version, DataType = typeof(object), - Steps = new WorkflowStepCollection() + Steps = new WorkflowStepCollection { step1 } From 6e53ad9a404b3d5ab3cf9bceaa0e21280acaa591 Mon Sep 17 00:00:00 2001 From: macrian Date: Thu, 11 Mar 2021 10:36:18 +0200 Subject: [PATCH 101/342] Cleanup using statements --- src/WorkflowCore.DSL/Models/DefinitionSource.cs | 2 -- src/WorkflowCore.DSL/Models/Envelope.cs | 2 -- src/WorkflowCore.DSL/Models/v1/MappingSourceV1.cs | 2 -- src/WorkflowCore.DSL/Models/v1/StepSourceV1.cs | 1 - src/WorkflowCore.DSL/ServiceCollectionExtensions.cs | 3 --- src/WorkflowCore.DSL/Services/DefinitionLoader.cs | 5 +---- .../Exceptions/WorkflowDefinitionLoadException.cs | 2 -- src/WorkflowCore/Interface/IActivityController.cs | 2 -- src/WorkflowCore/Interface/ICancellationProcessor.cs | 2 -- src/WorkflowCore/Interface/ILifeCycleEventHub.cs | 2 -- .../Interface/ILifeCycleEventPublisher.cs | 2 -- src/WorkflowCore/Interface/ISearchIndex.cs | 2 -- src/WorkflowCore/Interface/ISearchable.cs | 1 - src/WorkflowCore/Interface/IStepBuilder.cs | 2 -- src/WorkflowCore/Interface/IStepParameter.cs | 5 +---- src/WorkflowCore/Interface/IWorkflowController.cs | 2 -- src/WorkflowCore/Interface/IWorkflowErrorHandler.cs | 1 - src/WorkflowCore/Models/ActionParameter.cs | 2 -- src/WorkflowCore/Models/ActivityResult.cs | 2 -- src/WorkflowCore/Models/ExecutionPointerCollection.cs | 1 - .../Models/LifeCycleEvents/LifeCycleEvent.cs | 2 -- .../Models/LifeCycleEvents/StepCompleted.cs | 2 -- .../Models/LifeCycleEvents/StepStarted.cs | 2 -- .../Models/LifeCycleEvents/WorkflowCompleted.cs | 2 -- .../Models/LifeCycleEvents/WorkflowError.cs | 2 -- .../Models/LifeCycleEvents/WorkflowResumed.cs | 2 -- .../Models/LifeCycleEvents/WorkflowStarted.cs | 2 -- .../Models/LifeCycleEvents/WorkflowSuspended.cs | 2 -- .../Models/LifeCycleEvents/WorkflowTerminated.cs | 2 -- src/WorkflowCore/Models/MemberMapParameter.cs | 1 - src/WorkflowCore/Models/Search/Page.cs | 1 - src/WorkflowCore/Models/Search/SearchFilter.cs | 2 -- src/WorkflowCore/Models/Search/StepInfo.cs | 2 -- .../Models/Search/WorkflowSearchResult.cs | 2 -- src/WorkflowCore/Models/WorkflowDefinition.cs | 1 - src/WorkflowCore/Models/WorkflowInstance.cs | 1 - src/WorkflowCore/Models/WorkflowStep.cs | 1 - src/WorkflowCore/Models/WorkflowStepCollection.cs | 1 - src/WorkflowCore/Primitives/ContainerStepBody.cs | 1 - src/WorkflowCore/Primitives/SagaContainer.cs | 4 +--- src/WorkflowCore/Properties/AssemblyInfo.cs | 1 - src/WorkflowCore/ServiceCollectionExtensions.cs | 4 ---- src/WorkflowCore/Services/ActivityController.cs | 1 - .../Services/BackgroundTasks/WorkflowConsumer.cs | 1 - src/WorkflowCore/Services/CancellationProcessor.cs | 2 -- .../DefaultProviders/MemoryPersistenceProvider.cs | 1 - .../Services/DefaultProviders/NullSearchIndex.cs | 2 -- .../Services/DefaultProviders/SingleNodeEventHub.cs | 1 - .../TransientMemoryPersistenceProvider.cs | 1 - .../Services/ErrorHandlers/CompensateHandler.cs | 2 -- .../Services/ErrorHandlers/RetryHandler.cs | 2 -- .../Services/ErrorHandlers/SuspendHandler.cs | 1 - .../Services/ErrorHandlers/TerminateHandler.cs | 1 - src/WorkflowCore/Services/ExecutionPointerFactory.cs | 1 - src/WorkflowCore/Services/LifeCycleEventPublisher.cs | 2 -- src/WorkflowCore/Services/SyncWorkflowRunner.cs | 2 -- src/WorkflowCore/Services/WorkflowController.cs | 1 - src/WorkflowCore/Services/WorkflowHost.cs | 3 --- .../WorkflowCore.Users/Interface/IUserTaskBuilder.cs | 4 ---- .../Interface/IUserTaskReturnBuilder.cs | 2 -- .../WorkflowCore.Users/Models/OpenUserAction.cs | 1 - .../WorkflowCore.Users/Models/UserAction.cs | 2 -- src/extensions/WorkflowCore.Users/Models/UserStep.cs | 2 -- .../WorkflowCore.Users/Models/UserStepContainer.cs | 1 - .../WorkflowCore.Users/Primitives/Escalate.cs | 2 -- .../WorkflowCore.Users/Primitives/EscalateStep.cs | 4 ---- .../WorkflowCore.Users/Primitives/UserTaskStep.cs | 2 -- .../WorkflowCore.Users/Properties/AssemblyInfo.cs | 1 - .../ServiceExtensions/StepBuilderExtensions.cs | 4 ---- .../ServiceExtensions/WorkflowHostExtensions.cs | 3 --- .../WorkflowCore.Users/Services/UserTaskBuilder.cs | 2 -- .../Services/UserTaskReturnBuilder.cs | 2 -- .../Controllers/EventsController.cs | 1 - .../Controllers/WorkflowsController.cs | 1 - .../WorkflowCore.WebAPI/Properties/AssemblyInfo.cs | 1 - .../ServiceCollectionExtensions.cs | 2 -- .../ServiceCollectionExtensions.cs | 2 -- .../SqlLockProvider.cs | 1 - .../ExtensionMethods.cs | 1 - .../Interfaces/IWorkflowDbContextFactory.cs | 2 -- .../Models/PersistedEvent.cs | 2 -- .../Models/PersistedExecutionError.cs | 4 ---- .../Models/PersistedExecutionPointer.cs | 1 - .../Models/PersistedExecutionPointerCollection.cs | 1 - .../Models/PersistedExtensionAttribute.cs | 3 --- .../Models/PersistedSubscription.cs | 3 --- .../Models/PersistedWorkflow.cs | 3 --- .../Properties/AssemblyInfo.cs | 1 - .../Services/EntityFrameworkPersistenceProvider.cs | 4 ---- .../Services/WorkflowDbContext.cs | 6 ------ .../WorkflowCore.Persistence.MongoDB/ConfigOptions.cs | 2 -- .../Properties/AssemblyInfo.cs | 1 - .../ServiceCollectionExtensions.cs | 2 -- .../AssemblyQualifiedDiscriminatorConvention.cs | 2 -- .../MysqlPersistenceProviderModelSnapshot.cs | 2 -- .../Migrations/20170126230815_InitialDatabase.cs | 1 - .../Migrations/20170312161610_Events.cs | 1 - .../Migrations/20170507214430_ControlStructures.cs | 1 - .../Migrations/20170519231452_PersistOutcome.cs | 1 - .../Migrations/20170722200412_WfReference.cs | 1 - .../Migrations/20171223020844_StepScope.cs | 1 - .../PostgresPersistenceProviderModelSnapshot.cs | 2 -- .../PostgresContext.cs | 2 -- .../PostgresContextFactory.cs | 2 -- .../Properties/AssemblyInfo.cs | 1 - .../ServiceCollectionExtensions.cs | 2 -- .../RavenStoreOptions.cs | 2 -- .../ServiceCollectionExtensions.cs | 6 +----- .../Services/RavenDbIndexes.cs | 2 -- .../Services/RavendbPersistenceProvider.cs | 1 - .../Services/WorkflowPurger.cs | 4 ---- .../Migrations/20170126230839_InitialDatabase.cs | 1 - .../Migrations/20170312161610_Events.cs | 1 - .../Migrations/20170507214430_ControlStructures.cs | 1 - .../Migrations/20170519231452_PersistOutcome.cs | 1 - .../Migrations/20170722195832_WfReference.cs | 1 - .../Migrations/20171223020645_StepScope.cs | 1 - .../SqlServerPersistenceProviderModelSnapshot.cs | 3 --- .../Properties/AssemblyInfo.cs | 1 - .../ServiceCollectionExtensions.cs | 1 - .../SqlContextFactory.cs | 1 - .../SqlServerContext.cs | 2 -- .../Properties/AssemblyInfo.cs | 1 - .../ServiceCollectionExtensions.cs | 2 -- .../WorkflowCore.Persistence.Sqlite/SqliteContext.cs | 2 -- .../SqliteContextFactory.cs | 2 -- .../Interface/IKinesisStreamConsumer.cs | 2 -- .../Interface/IKinesisTracker.cs | 2 -- .../WorkflowCore.Providers.AWS/ModelExtensions.cs | 3 --- .../Services/DynamoDbProvisioner.cs | 1 - .../Services/DynamoPersistenceProvider.cs | 1 - .../Services/KinesisProvider.cs | 1 - .../Services/KinesisTracker.cs | 2 -- .../Models/ControlledLock.cs | 2 -- .../Models/PersistedEvent.cs | 1 - .../Models/PersistedSubscription.cs | 1 - .../Models/PersistedWorkflow.cs | 1 - .../Services/AzureLockManager.cs | 1 - .../Services/AzureStorageQueueProvider.cs | 1 - .../Services/CosmosDbPersistenceProvider.cs | 1 - .../Services/CosmosDbProvisioner.cs | 1 - .../Services/ElasticsearchIndexer.cs | 1 - .../ServiceCollectionExtensions.cs | 1 - .../Services/RedisLifeCycleEventHub.cs | 1 - .../Services/RedisLockProvider.cs | 1 - .../Services/RedisPersistenceProvider.cs | 1 - .../Services/RedisQueueProvider.cs | 1 - .../Properties/AssemblyInfo.cs | 1 - .../Services/RabbitMQProvider.cs | 3 --- .../Interfaces/ISqlServerQueueProviderMigrator.cs | 2 -- .../Models/QueueConfig.cs | 2 -- .../ServiceCollectionExtensions.cs | 2 -- .../Services/QueueConfigProvider.cs | 1 - .../Services/SqlCommandExecutor.cs | 2 -- .../Services/SqlServerQueueProviderMigrator.cs | 1 - .../WorkflowCore.Sample01/HelloWorldWorkflow.cs | 3 --- src/samples/WorkflowCore.Sample01/Program.cs | 4 ---- .../WorkflowCore.Sample01/Properties/AssemblyInfo.cs | 1 - .../WorkflowCore.Sample01/Steps/GoodbyeWorld.cs | 2 -- src/samples/WorkflowCore.Sample01/Steps/HelloWorld.cs | 2 -- src/samples/WorkflowCore.Sample02/Program.cs | 4 ---- .../WorkflowCore.Sample02/Properties/AssemblyInfo.cs | 1 - .../WorkflowCore.Sample02/SimpleDecisionWorkflow.cs | 2 -- .../WorkflowCore.Sample02/Steps/CustomMessage.cs | 2 -- .../WorkflowCore.Sample02/Steps/GoodbyeWorld.cs | 2 -- src/samples/WorkflowCore.Sample02/Steps/HelloWorld.cs | 2 -- .../WorkflowCore.Sample02/Steps/RandomOutput.cs | 2 -- src/samples/WorkflowCore.Sample03/MyDataClass.cs | 4 ---- .../WorkflowCore.Sample03/PassingDataWorkflow.cs | 2 -- src/samples/WorkflowCore.Sample03/Program.cs | 4 ---- .../WorkflowCore.Sample03/Properties/AssemblyInfo.cs | 1 - src/samples/WorkflowCore.Sample03/Steps/AddNumbers.cs | 1 - .../WorkflowCore.Sample03/Steps/CustomMessage.cs | 2 -- .../WorkflowCore.Sample03/Steps/GoodbyeWorld.cs | 2 -- src/samples/WorkflowCore.Sample03/Steps/HelloWorld.cs | 2 -- .../WorkflowCore.Sample04/EventSampleWorkflow.cs | 2 -- src/samples/WorkflowCore.Sample04/MyDataClass.cs | 2 -- src/samples/WorkflowCore.Sample04/Program.cs | 10 ---------- .../WorkflowCore.Sample04/Properties/AssemblyInfo.cs | 1 - .../WorkflowCore.Sample04/Steps/CustomMessage.cs | 2 -- .../WorkflowCore.Sample05/DeferSampleWorkflow.cs | 2 -- src/samples/WorkflowCore.Sample05/Program.cs | 6 ------ .../WorkflowCore.Sample05/Properties/AssemblyInfo.cs | 1 - src/samples/WorkflowCore.Sample05/Steps/SleepStep.cs | 2 -- .../WorkflowCore.Sample06/MultipleOutcomeWorkflow.cs | 2 -- src/samples/WorkflowCore.Sample06/Program.cs | 6 ------ .../WorkflowCore.Sample06/Properties/AssemblyInfo.cs | 1 - .../WorkflowCore.Sample06/Steps/RandomOutput.cs | 2 -- src/samples/WorkflowCore.Sample06/Steps/TaskA.cs | 2 -- src/samples/WorkflowCore.Sample06/Steps/TaskB.cs | 2 -- src/samples/WorkflowCore.Sample06/Steps/TaskC.cs | 2 -- src/samples/WorkflowCore.Sample06/Steps/TaskD.cs | 2 -- src/samples/WorkflowCore.Sample07/Program.cs | 2 -- src/samples/WorkflowCore.Sample07/Startup.cs | 3 --- src/samples/WorkflowCore.Sample08/HumanWorkflow.cs | 3 --- src/samples/WorkflowCore.Sample08/Program.cs | 3 --- .../WorkflowCore.Sample08/Properties/AssemblyInfo.cs | 1 - src/samples/WorkflowCore.Sample09/ForEachWorkflow.cs | 2 -- src/samples/WorkflowCore.Sample09/Program.cs | 1 - .../WorkflowCore.Sample09/Steps/DisplayContext.cs | 2 -- .../WorkflowCore.Sample09/Steps/DoSomething.cs | 2 -- src/samples/WorkflowCore.Sample09/Steps/SayGoodbye.cs | 2 -- src/samples/WorkflowCore.Sample09/Steps/SayHello.cs | 2 -- .../WorkflowCore.Sample09s/ForEachSyncWorkflow.cs | 2 -- src/samples/WorkflowCore.Sample09s/Program.cs | 1 - .../WorkflowCore.Sample09s/Steps/DisplayContext.cs | 2 -- .../WorkflowCore.Sample09s/Steps/DoSomething.cs | 2 -- .../WorkflowCore.Sample09s/Steps/SayGoodbye.cs | 2 -- src/samples/WorkflowCore.Sample09s/Steps/SayHello.cs | 2 -- src/samples/WorkflowCore.Sample10/Program.cs | 1 - .../WorkflowCore.Sample10/Steps/DoSomething.cs | 2 -- .../WorkflowCore.Sample10/Steps/IncrementStep.cs | 2 -- src/samples/WorkflowCore.Sample10/Steps/SayGoodbye.cs | 2 -- src/samples/WorkflowCore.Sample10/Steps/SayHello.cs | 2 -- src/samples/WorkflowCore.Sample10/WhileWorkflow.cs | 3 --- src/samples/WorkflowCore.Sample11/IfWorkflow.cs | 3 --- src/samples/WorkflowCore.Sample11/Program.cs | 1 - .../WorkflowCore.Sample11/Steps/PrintMessage.cs | 2 -- src/samples/WorkflowCore.Sample11/Steps/SayGoodbye.cs | 2 -- src/samples/WorkflowCore.Sample11/Steps/SayHello.cs | 2 -- src/samples/WorkflowCore.Sample12/OutcomeWorkflow.cs | 3 --- src/samples/WorkflowCore.Sample12/Program.cs | 1 - .../WorkflowCore.Sample12/Steps/DetermineSomething.cs | 3 --- .../WorkflowCore.Sample12/Steps/PrintMessage.cs | 2 -- src/samples/WorkflowCore.Sample12/Steps/SayGoodbye.cs | 2 -- src/samples/WorkflowCore.Sample12/Steps/SayHello.cs | 2 -- src/samples/WorkflowCore.Sample13/ParallelWorkflow.cs | 3 --- src/samples/WorkflowCore.Sample13/Program.cs | 5 ----- .../WorkflowCore.Sample13/Steps/PrintMessage.cs | 2 -- src/samples/WorkflowCore.Sample13/Steps/SayGoodbye.cs | 2 -- src/samples/WorkflowCore.Sample13/Steps/SayHello.cs | 2 -- src/samples/WorkflowCore.Sample14/Program.cs | 1 - .../WorkflowCore.Sample14/RecurSampleWorkflow.cs | 3 --- .../WorkflowCore.Sample15/HelloWorldWorkflow.cs | 3 --- src/samples/WorkflowCore.Sample15/Program.cs | 1 - .../WorkflowCore.Sample15/Services/MyService.cs | 2 -- .../WorkflowCore.Sample15/Steps/DoSomething.cs | 5 +---- src/samples/WorkflowCore.Sample15/Steps/HelloWorld.cs | 2 -- src/samples/WorkflowCore.Sample16/Program.cs | 1 - src/samples/WorkflowCore.Sample16/ScheduleWorkflow.cs | 2 -- .../WorkflowCore.Sample17/CompensatingWorkflow.cs | 3 --- src/samples/WorkflowCore.Sample18/ActivityWorkflow.cs | 3 --- src/samples/WorkflowCore.Sample18/Program.cs | 2 -- .../WorkflowCore.Sample18/Steps/CustomMessage.cs | 2 -- .../WorkflowCore.Sample18/Steps/GoodbyeWorld.cs | 2 -- src/samples/WorkflowCore.Sample18/Steps/HelloWorld.cs | 2 -- src/samples/WorkflowCore.Sample19/Program.cs | 1 - src/samples/WorkflowCore.TestSample01/NUnitTest.cs | 2 -- .../WorkflowCore.TestSample01/Workflow/AddNumbers.cs | 2 -- .../WorkflowCore.TestSample01/Workflow/MyDataClass.cs | 2 -- .../WorkflowCore.TestSample01/Workflow/MyWorkflow.cs | 2 -- test/Docker.Testify/DockerSetup.cs | 3 --- test/Docker.Testify/PortsInUseException.cs | 2 -- test/ScratchPad/ElasticTest.cs | 11 +---------- test/ScratchPad/Program.cs | 5 +---- .../Properties/AssemblyInfo.cs | 1 - .../Scenarios/ActivityScenario.cs | 2 -- .../Scenarios/AttachScenario.cs | 3 --- .../Scenarios/BaseScenario.cs | 2 -- .../Scenarios/BasicScenario.cs | 2 -- .../Scenarios/CancelledEventScenario.cs | 2 -- .../Scenarios/CompensationScenario.cs | 2 -- .../Scenarios/CompensationScenario2.cs | 2 -- .../Scenarios/DataIOScenario.cs | 2 -- .../Scenarios/DiScenario.cs | 1 - .../Scenarios/EndStepScenario.cs | 2 -- .../Scenarios/EventOrderScenario.cs | 2 -- .../Scenarios/EventScenario.cs | 2 -- .../Scenarios/FailingSagaScenario.cs | 2 -- .../Scenarios/ForeachScenario.cs | 1 - .../Scenarios/ForkScenario.cs | 2 -- .../Scenarios/IfScenario.cs | 2 -- .../Scenarios/MultistepCompensationScenario.cs | 2 -- .../Scenarios/NestedRetrySagaScenario.cs | 2 -- .../Scenarios/ParallelScenario.cs | 2 -- .../Scenarios/RetrySagaScenario.cs | 2 -- .../Scenarios/SagaScenario.cs | 2 -- .../Scenarios/StoredJsonScenario.cs | 4 ---- .../Scenarios/StoredYamlScenario.cs | 4 ---- .../Scenarios/UserScenario.cs | 4 ---- .../Scenarios/WhenScenario.cs | 2 -- .../Scenarios/WhileScenario.cs | 2 -- .../WorkflowCore.IntegrationTests/SearchIndexTests.cs | 3 --- .../WorkflowCore.TestAssets/DataTypes/CounterBoard.cs | 2 -- .../LockProvider/DistributedLockProviderTests.cs | 2 -- .../Properties/AssemblyInfo.cs | 1 - test/WorkflowCore.TestAssets/Steps/Counter.cs | 2 -- test/WorkflowCore.TestAssets/Utils.cs | 2 -- test/WorkflowCore.Testing/JsonWorkflowTest.cs | 2 -- test/WorkflowCore.Testing/WorkflowTest.cs | 2 -- test/WorkflowCore.Testing/YamlWorkflowTest.cs | 2 -- .../DynamoDbDockerSetup.cs | 7 +------ .../DynamoPersistenceProviderFixture.cs | 2 -- .../Scenarios/DynamoBasicScenario.cs | 4 ---- .../Scenarios/DynamoCompensationScenario.cs | 4 ---- .../Scenarios/DynamoDataScenario.cs | 4 ---- .../Scenarios/DynamoDynamicDataScenario.cs | 4 ---- .../Scenarios/DynamoEventScenario.cs | 4 ---- .../Scenarios/DynamoForeachScenario.cs | 4 ---- .../Scenarios/DynamoIfScenario.cs | 4 ---- .../Scenarios/DynamoRetrySagaScenario.cs | 4 ---- .../Scenarios/DynamoSagaScenario.cs | 4 ---- .../Scenarios/DynamoWhileScenario.cs | 4 ---- .../ElasticsearchDockerSetup.cs | 2 -- test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs | 7 +------ .../MongoPersistenceProviderFixture.cs | 2 -- .../Properties/AssemblyInfo.cs | 1 - .../Scenarios/MongoActivityScenario.cs | 2 -- .../Scenarios/MongoBasicScenario.cs | 2 -- .../Scenarios/MongoCompensationScenario.cs | 2 -- .../Scenarios/MongoDataScenario.cs | 2 -- .../Scenarios/MongoDecisionScenario.cs | 3 --- .../Scenarios/MongoEventScenario.cs | 2 -- .../Scenarios/MongoForEachScenario.cs | 2 -- .../Scenarios/MongoForkScenario.cs | 2 -- .../Scenarios/MongoIfScenario.cs | 2 -- .../Scenarios/MongoRetrySagaScenario.cs | 2 -- .../Scenarios/MongoSagaScenario.cs | 2 -- .../Scenarios/MongoUserScenario.cs | 2 -- .../Scenarios/MongoWhenScenario.cs | 2 -- .../Scenarios/MongoWhileScenario.cs | 2 -- .../Scenarios/MysqlDynamicDataScenario.cs | 1 - .../Scenarios/MysqlEventScenario.cs | 3 --- .../Scenarios/MysqlForeachScenario.cs | 3 --- .../Scenarios/MysqlForkScenario.cs | 3 --- .../Scenarios/MysqlIfScenario.cs | 3 --- .../Scenarios/MysqlRetrySagaScenario.cs | 3 --- .../Scenarios/MysqlSagaScenario.cs | 3 --- .../Scenarios/MysqlUserScenario.cs | 3 --- .../Scenarios/MysqlWhenScenario.cs | 3 --- .../Scenarios/MysqlWhileScenario.cs | 3 --- test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs | 7 +------ .../PostgresPersistenceProviderFixture.cs | 2 -- .../Properties/AssemblyInfo.cs | 1 - .../Scenarios/PostgresActivityScenario.cs | 2 -- .../Scenarios/PostgresBasicScenario.cs | 2 -- .../Scenarios/PostgresDataScenario.cs | 2 -- .../Scenarios/PostgresEventScenario.cs | 2 -- .../Scenarios/PostgresForeachScenario.cs | 2 -- .../Scenarios/PostgresForkScenario.cs | 2 -- .../Scenarios/PostgresIfScenario.cs | 2 -- .../Scenarios/PostgresRetrySagaScenario.cs | 2 -- .../Scenarios/PostgresSagaScenario.cs | 2 -- .../Scenarios/PostgresUserScenario.cs | 2 -- .../Scenarios/PostgresWhenScenario.cs | 2 -- .../Scenarios/PostgresWhileScenario.cs | 2 -- test/WorkflowCore.Tests.Redis/RedisDockerSetup.cs | 6 +----- .../RedisPersistenceProviderFixture.cs | 2 -- test/WorkflowCore.Tests.SqlServer/DockerSetup.cs | 7 +------ .../Scenarios/SqlServerActivityScenario.cs | 2 -- .../Scenarios/SqlServerBasicScenario.cs | 2 -- .../Scenarios/SqlServerCompenstationScenario.cs | 2 -- .../Scenarios/SqlServerDataScenario.cs | 2 -- .../Scenarios/SqlServerEventScenario.cs | 2 -- .../Scenarios/SqlServerForEachScenario.cs | 2 -- .../Scenarios/SqlServerIfScenario.cs | 2 -- .../Scenarios/SqlServerRetrySagaScenario.cs | 2 -- .../Scenarios/SqlServerSagaScenario.cs | 2 -- .../Scenarios/SqlServerWhenScenario.cs | 2 -- .../Scenarios/SqlServerWhileScenario.cs | 2 -- test/WorkflowCore.Tests.Sqlite/SqliteCollection.cs | 2 -- .../SqlitePersistenceProviderFixture.cs | 2 -- .../Models/MemberMapParameterTests.cs | 1 - .../WorkflowCore.UnitTests/Properties/AssemblyInfo.cs | 1 - .../DefinitionStorage/DefinitionLoaderTests.cs | 4 ---- .../Services/ExecutionResultProcessorFixture.cs | 3 --- .../Services/MemoryPersistenceProviderFixture.cs | 2 -- .../Services/WorkflowRegistryFixture.cs | 8 -------- .../SingleNodeLockProviderTests.cs | 5 +---- 369 files changed, 13 insertions(+), 798 deletions(-) diff --git a/src/WorkflowCore.DSL/Models/DefinitionSource.cs b/src/WorkflowCore.DSL/Models/DefinitionSource.cs index 5d2bf0333..ec23f81c4 100644 --- a/src/WorkflowCore.DSL/Models/DefinitionSource.cs +++ b/src/WorkflowCore.DSL/Models/DefinitionSource.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.DefinitionStorage { diff --git a/src/WorkflowCore.DSL/Models/Envelope.cs b/src/WorkflowCore.DSL/Models/Envelope.cs index 77448f446..7258a6d5d 100644 --- a/src/WorkflowCore.DSL/Models/Envelope.cs +++ b/src/WorkflowCore.DSL/Models/Envelope.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.DefinitionStorage { diff --git a/src/WorkflowCore.DSL/Models/v1/MappingSourceV1.cs b/src/WorkflowCore.DSL/Models/v1/MappingSourceV1.cs index 94c21e3be..d4d920544 100644 --- a/src/WorkflowCore.DSL/Models/v1/MappingSourceV1.cs +++ b/src/WorkflowCore.DSL/Models/v1/MappingSourceV1.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.DefinitionStorage.v1 { diff --git a/src/WorkflowCore.DSL/Models/v1/StepSourceV1.cs b/src/WorkflowCore.DSL/Models/v1/StepSourceV1.cs index 82969d765..fb67ba449 100644 --- a/src/WorkflowCore.DSL/Models/v1/StepSourceV1.cs +++ b/src/WorkflowCore.DSL/Models/v1/StepSourceV1.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Dynamic; -using System.Text; namespace WorkflowCore.Models.DefinitionStorage.v1 { diff --git a/src/WorkflowCore.DSL/ServiceCollectionExtensions.cs b/src/WorkflowCore.DSL/ServiceCollectionExtensions.cs index 113236e91..5c4944f4f 100644 --- a/src/WorkflowCore.DSL/ServiceCollectionExtensions.cs +++ b/src/WorkflowCore.DSL/ServiceCollectionExtensions.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; using WorkflowCore.Interface; using WorkflowCore.Services.DefinitionStorage; diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index d408bfc07..b057b223a 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -1,17 +1,14 @@ -using Newtonsoft.Json; -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Dynamic.Core; using System.Linq.Expressions; using System.Reflection; -using System.Text; using Newtonsoft.Json.Linq; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Primitives; -using WorkflowCore.Models.DefinitionStorage; using WorkflowCore.Models.DefinitionStorage.v1; using WorkflowCore.Exceptions; diff --git a/src/WorkflowCore/Exceptions/WorkflowDefinitionLoadException.cs b/src/WorkflowCore/Exceptions/WorkflowDefinitionLoadException.cs index 0ceb5ab38..6cc35d6f0 100644 --- a/src/WorkflowCore/Exceptions/WorkflowDefinitionLoadException.cs +++ b/src/WorkflowCore/Exceptions/WorkflowDefinitionLoadException.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Exceptions { diff --git a/src/WorkflowCore/Interface/IActivityController.cs b/src/WorkflowCore/Interface/IActivityController.cs index 99e5c1737..46464e8e8 100644 --- a/src/WorkflowCore/Interface/IActivityController.cs +++ b/src/WorkflowCore/Interface/IActivityController.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; namespace WorkflowCore.Interface diff --git a/src/WorkflowCore/Interface/ICancellationProcessor.cs b/src/WorkflowCore/Interface/ICancellationProcessor.cs index 09d37969b..f6cbb31fa 100644 --- a/src/WorkflowCore/Interface/ICancellationProcessor.cs +++ b/src/WorkflowCore/Interface/ICancellationProcessor.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Models; namespace WorkflowCore.Interface diff --git a/src/WorkflowCore/Interface/ILifeCycleEventHub.cs b/src/WorkflowCore/Interface/ILifeCycleEventHub.cs index 70663effc..6ce3fb177 100644 --- a/src/WorkflowCore/Interface/ILifeCycleEventHub.cs +++ b/src/WorkflowCore/Interface/ILifeCycleEventHub.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; using WorkflowCore.Models.LifeCycleEvents; diff --git a/src/WorkflowCore/Interface/ILifeCycleEventPublisher.cs b/src/WorkflowCore/Interface/ILifeCycleEventPublisher.cs index 273c26456..db703659a 100644 --- a/src/WorkflowCore/Interface/ILifeCycleEventPublisher.cs +++ b/src/WorkflowCore/Interface/ILifeCycleEventPublisher.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Models.LifeCycleEvents; namespace WorkflowCore.Interface diff --git a/src/WorkflowCore/Interface/ISearchIndex.cs b/src/WorkflowCore/Interface/ISearchIndex.cs index 64bd075f6..0aea590a8 100644 --- a/src/WorkflowCore/Interface/ISearchIndex.cs +++ b/src/WorkflowCore/Interface/ISearchIndex.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; using WorkflowCore.Models; using WorkflowCore.Models.Search; diff --git a/src/WorkflowCore/Interface/ISearchable.cs b/src/WorkflowCore/Interface/ISearchable.cs index 9ceec14e2..e769f916c 100644 --- a/src/WorkflowCore/Interface/ISearchable.cs +++ b/src/WorkflowCore/Interface/ISearchable.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Interface { diff --git a/src/WorkflowCore/Interface/IStepBuilder.cs b/src/WorkflowCore/Interface/IStepBuilder.cs index c654a9d20..e20d585c5 100644 --- a/src/WorkflowCore/Interface/IStepBuilder.cs +++ b/src/WorkflowCore/Interface/IStepBuilder.cs @@ -1,8 +1,6 @@ using System; -using System.Collections; using System.Linq.Expressions; using WorkflowCore.Models; -using WorkflowCore.Primitives; namespace WorkflowCore.Interface { diff --git a/src/WorkflowCore/Interface/IStepParameter.cs b/src/WorkflowCore/Interface/IStepParameter.cs index 049ecdb25..5bbbb2fbf 100644 --- a/src/WorkflowCore/Interface/IStepParameter.cs +++ b/src/WorkflowCore/Interface/IStepParameter.cs @@ -1,7 +1,4 @@ -using WorkflowCore.Interface; -using WorkflowCore.Models; - -namespace WorkflowCore.Interface +namespace WorkflowCore.Interface { public interface IStepParameter { diff --git a/src/WorkflowCore/Interface/IWorkflowController.cs b/src/WorkflowCore/Interface/IWorkflowController.cs index 89e7fc3c6..924925d2c 100644 --- a/src/WorkflowCore/Interface/IWorkflowController.cs +++ b/src/WorkflowCore/Interface/IWorkflowController.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; namespace WorkflowCore.Interface diff --git a/src/WorkflowCore/Interface/IWorkflowErrorHandler.cs b/src/WorkflowCore/Interface/IWorkflowErrorHandler.cs index 479176627..fa0734118 100644 --- a/src/WorkflowCore/Interface/IWorkflowErrorHandler.cs +++ b/src/WorkflowCore/Interface/IWorkflowErrorHandler.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; using WorkflowCore.Models; namespace WorkflowCore.Interface diff --git a/src/WorkflowCore/Models/ActionParameter.cs b/src/WorkflowCore/Models/ActionParameter.cs index f6a3e4723..762a865e8 100644 --- a/src/WorkflowCore/Models/ActionParameter.cs +++ b/src/WorkflowCore/Models/ActionParameter.cs @@ -1,7 +1,5 @@ using System; using System.Linq; -using System.Linq.Expressions; -using System.Reflection; using WorkflowCore.Interface; namespace WorkflowCore.Models diff --git a/src/WorkflowCore/Models/ActivityResult.cs b/src/WorkflowCore/Models/ActivityResult.cs index 212ca92d8..f3a828a08 100644 --- a/src/WorkflowCore/Models/ActivityResult.cs +++ b/src/WorkflowCore/Models/ActivityResult.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models { diff --git a/src/WorkflowCore/Models/ExecutionPointerCollection.cs b/src/WorkflowCore/Models/ExecutionPointerCollection.cs index 90e64348c..f125db5a8 100644 --- a/src/WorkflowCore/Models/ExecutionPointerCollection.cs +++ b/src/WorkflowCore/Models/ExecutionPointerCollection.cs @@ -2,7 +2,6 @@ using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Text; namespace WorkflowCore.Models { diff --git a/src/WorkflowCore/Models/LifeCycleEvents/LifeCycleEvent.cs b/src/WorkflowCore/Models/LifeCycleEvents/LifeCycleEvent.cs index afab488b0..f72283e9a 100755 --- a/src/WorkflowCore/Models/LifeCycleEvents/LifeCycleEvent.cs +++ b/src/WorkflowCore/Models/LifeCycleEvents/LifeCycleEvent.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.LifeCycleEvents { diff --git a/src/WorkflowCore/Models/LifeCycleEvents/StepCompleted.cs b/src/WorkflowCore/Models/LifeCycleEvents/StepCompleted.cs index 38a68697d..3d44be288 100644 --- a/src/WorkflowCore/Models/LifeCycleEvents/StepCompleted.cs +++ b/src/WorkflowCore/Models/LifeCycleEvents/StepCompleted.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.LifeCycleEvents { diff --git a/src/WorkflowCore/Models/LifeCycleEvents/StepStarted.cs b/src/WorkflowCore/Models/LifeCycleEvents/StepStarted.cs index a76c50e0f..183dd1a7b 100644 --- a/src/WorkflowCore/Models/LifeCycleEvents/StepStarted.cs +++ b/src/WorkflowCore/Models/LifeCycleEvents/StepStarted.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.LifeCycleEvents { diff --git a/src/WorkflowCore/Models/LifeCycleEvents/WorkflowCompleted.cs b/src/WorkflowCore/Models/LifeCycleEvents/WorkflowCompleted.cs index 4b3d8a2e2..e83da1827 100644 --- a/src/WorkflowCore/Models/LifeCycleEvents/WorkflowCompleted.cs +++ b/src/WorkflowCore/Models/LifeCycleEvents/WorkflowCompleted.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.LifeCycleEvents { diff --git a/src/WorkflowCore/Models/LifeCycleEvents/WorkflowError.cs b/src/WorkflowCore/Models/LifeCycleEvents/WorkflowError.cs index 55f273d63..e24849fcf 100644 --- a/src/WorkflowCore/Models/LifeCycleEvents/WorkflowError.cs +++ b/src/WorkflowCore/Models/LifeCycleEvents/WorkflowError.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.LifeCycleEvents { diff --git a/src/WorkflowCore/Models/LifeCycleEvents/WorkflowResumed.cs b/src/WorkflowCore/Models/LifeCycleEvents/WorkflowResumed.cs index 88f2ee603..1c400b84d 100644 --- a/src/WorkflowCore/Models/LifeCycleEvents/WorkflowResumed.cs +++ b/src/WorkflowCore/Models/LifeCycleEvents/WorkflowResumed.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.LifeCycleEvents { diff --git a/src/WorkflowCore/Models/LifeCycleEvents/WorkflowStarted.cs b/src/WorkflowCore/Models/LifeCycleEvents/WorkflowStarted.cs index c461ee8aa..60b906de8 100644 --- a/src/WorkflowCore/Models/LifeCycleEvents/WorkflowStarted.cs +++ b/src/WorkflowCore/Models/LifeCycleEvents/WorkflowStarted.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.LifeCycleEvents { diff --git a/src/WorkflowCore/Models/LifeCycleEvents/WorkflowSuspended.cs b/src/WorkflowCore/Models/LifeCycleEvents/WorkflowSuspended.cs index 39d19a7a8..ccadff82d 100644 --- a/src/WorkflowCore/Models/LifeCycleEvents/WorkflowSuspended.cs +++ b/src/WorkflowCore/Models/LifeCycleEvents/WorkflowSuspended.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.LifeCycleEvents { diff --git a/src/WorkflowCore/Models/LifeCycleEvents/WorkflowTerminated.cs b/src/WorkflowCore/Models/LifeCycleEvents/WorkflowTerminated.cs index 07ff8f75f..778c23493 100644 --- a/src/WorkflowCore/Models/LifeCycleEvents/WorkflowTerminated.cs +++ b/src/WorkflowCore/Models/LifeCycleEvents/WorkflowTerminated.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.LifeCycleEvents { diff --git a/src/WorkflowCore/Models/MemberMapParameter.cs b/src/WorkflowCore/Models/MemberMapParameter.cs index 052f0bc1a..e5273986d 100644 --- a/src/WorkflowCore/Models/MemberMapParameter.cs +++ b/src/WorkflowCore/Models/MemberMapParameter.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using System.Linq.Expressions; -using System.Reflection; using WorkflowCore.Interface; namespace WorkflowCore.Models diff --git a/src/WorkflowCore/Models/Search/Page.cs b/src/WorkflowCore/Models/Search/Page.cs index 63658fd37..412688a28 100644 --- a/src/WorkflowCore/Models/Search/Page.cs +++ b/src/WorkflowCore/Models/Search/Page.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.Search { diff --git a/src/WorkflowCore/Models/Search/SearchFilter.cs b/src/WorkflowCore/Models/Search/SearchFilter.cs index b4d7ff66b..e7491806c 100644 --- a/src/WorkflowCore/Models/Search/SearchFilter.cs +++ b/src/WorkflowCore/Models/Search/SearchFilter.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq.Expressions; -using System.Text; namespace WorkflowCore.Models.Search { diff --git a/src/WorkflowCore/Models/Search/StepInfo.cs b/src/WorkflowCore/Models/Search/StepInfo.cs index b17ccedd0..6b9a97d8f 100644 --- a/src/WorkflowCore/Models/Search/StepInfo.cs +++ b/src/WorkflowCore/Models/Search/StepInfo.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Models.Search { diff --git a/src/WorkflowCore/Models/Search/WorkflowSearchResult.cs b/src/WorkflowCore/Models/Search/WorkflowSearchResult.cs index 6870d36ab..1cb6a3c9a 100644 --- a/src/WorkflowCore/Models/Search/WorkflowSearchResult.cs +++ b/src/WorkflowCore/Models/Search/WorkflowSearchResult.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Reflection; -using WorkflowCore.Interface; namespace WorkflowCore.Models.Search { diff --git a/src/WorkflowCore/Models/WorkflowDefinition.cs b/src/WorkflowCore/Models/WorkflowDefinition.cs index 207457e19..0cea6cc40 100644 --- a/src/WorkflowCore/Models/WorkflowDefinition.cs +++ b/src/WorkflowCore/Models/WorkflowDefinition.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; namespace WorkflowCore.Models diff --git a/src/WorkflowCore/Models/WorkflowInstance.cs b/src/WorkflowCore/Models/WorkflowInstance.cs index b75b284fc..ca683d74a 100644 --- a/src/WorkflowCore/Models/WorkflowInstance.cs +++ b/src/WorkflowCore/Models/WorkflowInstance.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; namespace WorkflowCore.Models diff --git a/src/WorkflowCore/Models/WorkflowStep.cs b/src/WorkflowCore/Models/WorkflowStep.cs index 08ad1c525..814219916 100644 --- a/src/WorkflowCore/Models/WorkflowStep.cs +++ b/src/WorkflowCore/Models/WorkflowStep.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; -using System.Reflection; using WorkflowCore.Interface; namespace WorkflowCore.Models diff --git a/src/WorkflowCore/Models/WorkflowStepCollection.cs b/src/WorkflowCore/Models/WorkflowStepCollection.cs index 90c2e4710..68346620e 100644 --- a/src/WorkflowCore/Models/WorkflowStepCollection.cs +++ b/src/WorkflowCore/Models/WorkflowStepCollection.cs @@ -2,7 +2,6 @@ using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Text; namespace WorkflowCore.Models { diff --git a/src/WorkflowCore/Primitives/ContainerStepBody.cs b/src/WorkflowCore/Primitives/ContainerStepBody.cs index 30ad9b644..46da6a0b0 100644 --- a/src/WorkflowCore/Primitives/ContainerStepBody.cs +++ b/src/WorkflowCore/Primitives/ContainerStepBody.cs @@ -1,5 +1,4 @@ using System.Linq; -using System.Collections.Generic; using WorkflowCore.Models; namespace WorkflowCore.Primitives diff --git a/src/WorkflowCore/Primitives/SagaContainer.cs b/src/WorkflowCore/Primitives/SagaContainer.cs index 2034f6bd4..93470cdbb 100644 --- a/src/WorkflowCore/Primitives/SagaContainer.cs +++ b/src/WorkflowCore/Primitives/SagaContainer.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using WorkflowCore.Exceptions; -using WorkflowCore.Interface; +using WorkflowCore.Interface; using WorkflowCore.Models; namespace WorkflowCore.Primitives diff --git a/src/WorkflowCore/Properties/AssemblyInfo.cs b/src/WorkflowCore/Properties/AssemblyInfo.cs index d692f8bbb..2d7f37b38 100644 --- a/src/WorkflowCore/Properties/AssemblyInfo.cs +++ b/src/WorkflowCore/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/WorkflowCore/ServiceCollectionExtensions.cs b/src/WorkflowCore/ServiceCollectionExtensions.cs index 94634db96..760a89d41 100644 --- a/src/WorkflowCore/ServiceCollectionExtensions.cs +++ b/src/WorkflowCore/ServiceCollectionExtensions.cs @@ -1,12 +1,8 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; using WorkflowCore.Interface; using WorkflowCore.Services; using WorkflowCore.Models; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.ObjectPool; using WorkflowCore.Primitives; using WorkflowCore.Services.BackgroundTasks; diff --git a/src/WorkflowCore/Services/ActivityController.cs b/src/WorkflowCore/Services/ActivityController.cs index 04af6ef9f..e37481521 100644 --- a/src/WorkflowCore/Services/ActivityController.cs +++ b/src/WorkflowCore/Services/ActivityController.cs @@ -1,5 +1,4 @@ using System; -using System.Dynamic; using System.Linq; using System.Text; using System.Threading; diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index 6ce3776b5..9cda8206c 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -2,7 +2,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.ObjectPool; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/WorkflowCore/Services/CancellationProcessor.cs b/src/WorkflowCore/Services/CancellationProcessor.cs index 3ee58e287..4e56de9ea 100644 --- a/src/WorkflowCore/Services/CancellationProcessor.cs +++ b/src/WorkflowCore/Services/CancellationProcessor.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using Microsoft.Extensions.Logging; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs b/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs index fd27db8ca..9d64b689c 100644 --- a/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs +++ b/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; diff --git a/src/WorkflowCore/Services/DefaultProviders/NullSearchIndex.cs b/src/WorkflowCore/Services/DefaultProviders/NullSearchIndex.cs index db66ccf57..40d13fa9c 100644 --- a/src/WorkflowCore/Services/DefaultProviders/NullSearchIndex.cs +++ b/src/WorkflowCore/Services/DefaultProviders/NullSearchIndex.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/WorkflowCore/Services/DefaultProviders/SingleNodeEventHub.cs b/src/WorkflowCore/Services/DefaultProviders/SingleNodeEventHub.cs index 40a826b91..007b51efb 100644 --- a/src/WorkflowCore/Services/DefaultProviders/SingleNodeEventHub.cs +++ b/src/WorkflowCore/Services/DefaultProviders/SingleNodeEventHub.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using WorkflowCore.Interface; diff --git a/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs b/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs index 6b3084a89..466fc85e6 100644 --- a/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs +++ b/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs index dfc13af36..028f0d112 100644 --- a/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; -using WorkflowCore.Models.LifeCycleEvents; namespace WorkflowCore.Services.ErrorHandlers { diff --git a/src/WorkflowCore/Services/ErrorHandlers/RetryHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/RetryHandler.cs index 0a4d54810..84fbe5bd3 100644 --- a/src/WorkflowCore/Services/ErrorHandlers/RetryHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/RetryHandler.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; -using WorkflowCore.Models.LifeCycleEvents; namespace WorkflowCore.Services.ErrorHandlers { diff --git a/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs index 7c5fad05b..20ff0bab3 100755 --- a/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Models.LifeCycleEvents; diff --git a/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs index 89fb05eae..573bd7f17 100755 --- a/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Models.LifeCycleEvents; diff --git a/src/WorkflowCore/Services/ExecutionPointerFactory.cs b/src/WorkflowCore/Services/ExecutionPointerFactory.cs index 937e83d99..5bd4b2846 100644 --- a/src/WorkflowCore/Services/ExecutionPointerFactory.cs +++ b/src/WorkflowCore/Services/ExecutionPointerFactory.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/WorkflowCore/Services/LifeCycleEventPublisher.cs b/src/WorkflowCore/Services/LifeCycleEventPublisher.cs index 25334bcd2..ffebb332e 100644 --- a/src/WorkflowCore/Services/LifeCycleEventPublisher.cs +++ b/src/WorkflowCore/Services/LifeCycleEventPublisher.cs @@ -1,8 +1,6 @@ using Microsoft.Extensions.Logging; using System; using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Threading; using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models.LifeCycleEvents; diff --git a/src/WorkflowCore/Services/SyncWorkflowRunner.cs b/src/WorkflowCore/Services/SyncWorkflowRunner.cs index 293c976a0..1ff8326fa 100644 --- a/src/WorkflowCore/Services/SyncWorkflowRunner.cs +++ b/src/WorkflowCore/Services/SyncWorkflowRunner.cs @@ -1,11 +1,9 @@ using System; -using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using WorkflowCore.Exceptions; using WorkflowCore.Interface; using WorkflowCore.Models; -using WorkflowCore.Models.LifeCycleEvents; namespace WorkflowCore.Services { diff --git a/src/WorkflowCore/Services/WorkflowController.cs b/src/WorkflowCore/Services/WorkflowController.cs index 576c1b981..4cc591de5 100755 --- a/src/WorkflowCore/Services/WorkflowController.cs +++ b/src/WorkflowCore/Services/WorkflowController.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using System.Reflection; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; diff --git a/src/WorkflowCore/Services/WorkflowHost.cs b/src/WorkflowCore/Services/WorkflowHost.cs index aa08ba727..2a7fcc330 100644 --- a/src/WorkflowCore/Services/WorkflowHost.cs +++ b/src/WorkflowCore/Services/WorkflowHost.cs @@ -6,9 +6,6 @@ using Microsoft.Extensions.Logging; using WorkflowCore.Interface; using WorkflowCore.Models; -using System.Reflection; -using Microsoft.Extensions.DependencyInjection; -using WorkflowCore.Exceptions; using WorkflowCore.Models.LifeCycleEvents; namespace WorkflowCore.Services diff --git a/src/extensions/WorkflowCore.Users/Interface/IUserTaskBuilder.cs b/src/extensions/WorkflowCore.Users/Interface/IUserTaskBuilder.cs index e1df05ac6..9451ced29 100644 --- a/src/extensions/WorkflowCore.Users/Interface/IUserTaskBuilder.cs +++ b/src/extensions/WorkflowCore.Users/Interface/IUserTaskBuilder.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; using System.Linq.Expressions; -using System.Text; using WorkflowCore.Interface; -using WorkflowCore.Primitives; using WorkflowCore.Users.Primitives; -using WorkflowCore.Users.Services; namespace WorkflowCore.Users.Interface { diff --git a/src/extensions/WorkflowCore.Users/Interface/IUserTaskReturnBuilder.cs b/src/extensions/WorkflowCore.Users/Interface/IUserTaskReturnBuilder.cs index b6eed494c..37ee22b18 100644 --- a/src/extensions/WorkflowCore.Users/Interface/IUserTaskReturnBuilder.cs +++ b/src/extensions/WorkflowCore.Users/Interface/IUserTaskReturnBuilder.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Primitives; diff --git a/src/extensions/WorkflowCore.Users/Models/OpenUserAction.cs b/src/extensions/WorkflowCore.Users/Models/OpenUserAction.cs index 5d2ed8b8a..1452452a1 100644 --- a/src/extensions/WorkflowCore.Users/Models/OpenUserAction.cs +++ b/src/extensions/WorkflowCore.Users/Models/OpenUserAction.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; namespace WorkflowCore.Users.Models { diff --git a/src/extensions/WorkflowCore.Users/Models/UserAction.cs b/src/extensions/WorkflowCore.Users/Models/UserAction.cs index 61d5b4c48..d4d769824 100644 --- a/src/extensions/WorkflowCore.Users/Models/UserAction.cs +++ b/src/extensions/WorkflowCore.Users/Models/UserAction.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; namespace WorkflowCore.Users.Models { diff --git a/src/extensions/WorkflowCore.Users/Models/UserStep.cs b/src/extensions/WorkflowCore.Users/Models/UserStep.cs index e1f4b0c09..b8c147f65 100644 --- a/src/extensions/WorkflowCore.Users/Models/UserStep.cs +++ b/src/extensions/WorkflowCore.Users/Models/UserStep.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/extensions/WorkflowCore.Users/Models/UserStepContainer.cs b/src/extensions/WorkflowCore.Users/Models/UserStepContainer.cs index 0b3b348e4..e4238b9cc 100644 --- a/src/extensions/WorkflowCore.Users/Models/UserStepContainer.cs +++ b/src/extensions/WorkflowCore.Users/Models/UserStepContainer.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/extensions/WorkflowCore.Users/Primitives/Escalate.cs b/src/extensions/WorkflowCore.Users/Primitives/Escalate.cs index bdd8c6518..7a400bb87 100644 --- a/src/extensions/WorkflowCore.Users/Primitives/Escalate.cs +++ b/src/extensions/WorkflowCore.Users/Primitives/Escalate.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/extensions/WorkflowCore.Users/Primitives/EscalateStep.cs b/src/extensions/WorkflowCore.Users/Primitives/EscalateStep.cs index 7ed21b795..a56e000d3 100644 --- a/src/extensions/WorkflowCore.Users/Primitives/EscalateStep.cs +++ b/src/extensions/WorkflowCore.Users/Primitives/EscalateStep.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Text; -using WorkflowCore.Interface; using WorkflowCore.Models; namespace WorkflowCore.Users.Primitives diff --git a/src/extensions/WorkflowCore.Users/Primitives/UserTaskStep.cs b/src/extensions/WorkflowCore.Users/Primitives/UserTaskStep.cs index f12696d41..cc568019b 100644 --- a/src/extensions/WorkflowCore.Users/Primitives/UserTaskStep.cs +++ b/src/extensions/WorkflowCore.Users/Primitives/UserTaskStep.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/extensions/WorkflowCore.Users/Properties/AssemblyInfo.cs b/src/extensions/WorkflowCore.Users/Properties/AssemblyInfo.cs index 4a776a642..fa59636da 100644 --- a/src/extensions/WorkflowCore.Users/Properties/AssemblyInfo.cs +++ b/src/extensions/WorkflowCore.Users/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/extensions/WorkflowCore.Users/ServiceExtensions/StepBuilderExtensions.cs b/src/extensions/WorkflowCore.Users/ServiceExtensions/StepBuilderExtensions.cs index 3330c123b..2b337c1fd 100644 --- a/src/extensions/WorkflowCore.Users/ServiceExtensions/StepBuilderExtensions.cs +++ b/src/extensions/WorkflowCore.Users/ServiceExtensions/StepBuilderExtensions.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using System.Threading.Tasks; -using WorkflowCore.Interface; using WorkflowCore.Models; -using WorkflowCore.Primitives; using WorkflowCore.Services; using WorkflowCore.Users.Interface; using WorkflowCore.Users.Models; diff --git a/src/extensions/WorkflowCore.Users/ServiceExtensions/WorkflowHostExtensions.cs b/src/extensions/WorkflowCore.Users/ServiceExtensions/WorkflowHostExtensions.cs index 89b753f52..606d5592f 100644 --- a/src/extensions/WorkflowCore.Users/ServiceExtensions/WorkflowHostExtensions.cs +++ b/src/extensions/WorkflowCore.Users/ServiceExtensions/WorkflowHostExtensions.cs @@ -1,11 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; using System.Threading.Tasks; -using WorkflowCore.Interface; using WorkflowCore.Models; -using WorkflowCore.Services; using WorkflowCore.Users.Models; using WorkflowCore.Users.Primitives; diff --git a/src/extensions/WorkflowCore.Users/Services/UserTaskBuilder.cs b/src/extensions/WorkflowCore.Users/Services/UserTaskBuilder.cs index 5ea5da8db..ccba7b239 100644 --- a/src/extensions/WorkflowCore.Users/Services/UserTaskBuilder.cs +++ b/src/extensions/WorkflowCore.Users/Services/UserTaskBuilder.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq.Expressions; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Primitives; diff --git a/src/extensions/WorkflowCore.Users/Services/UserTaskReturnBuilder.cs b/src/extensions/WorkflowCore.Users/Services/UserTaskReturnBuilder.cs index 70438ba8b..6bc06be4b 100644 --- a/src/extensions/WorkflowCore.Users/Services/UserTaskReturnBuilder.cs +++ b/src/extensions/WorkflowCore.Users/Services/UserTaskReturnBuilder.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Primitives; diff --git a/src/extensions/WorkflowCore.WebAPI/Controllers/EventsController.cs b/src/extensions/WorkflowCore.WebAPI/Controllers/EventsController.cs index f2ec00029..4930aa22d 100644 --- a/src/extensions/WorkflowCore.WebAPI/Controllers/EventsController.cs +++ b/src/extensions/WorkflowCore.WebAPI/Controllers/EventsController.cs @@ -1,7 +1,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using WorkflowCore.Interface; diff --git a/src/extensions/WorkflowCore.WebAPI/Controllers/WorkflowsController.cs b/src/extensions/WorkflowCore.WebAPI/Controllers/WorkflowsController.cs index f4200b13c..3c88df3fb 100644 --- a/src/extensions/WorkflowCore.WebAPI/Controllers/WorkflowsController.cs +++ b/src/extensions/WorkflowCore.WebAPI/Controllers/WorkflowsController.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; diff --git a/src/extensions/WorkflowCore.WebAPI/Properties/AssemblyInfo.cs b/src/extensions/WorkflowCore.WebAPI/Properties/AssemblyInfo.cs index 3ad8e3878..b5a5d4e35 100644 --- a/src/extensions/WorkflowCore.WebAPI/Properties/AssemblyInfo.cs +++ b/src/extensions/WorkflowCore.WebAPI/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/extensions/WorkflowCore.WebAPI/ServiceCollectionExtensions.cs b/src/extensions/WorkflowCore.WebAPI/ServiceCollectionExtensions.cs index bfe6bbd73..3a2ead3db 100644 --- a/src/extensions/WorkflowCore.WebAPI/ServiceCollectionExtensions.cs +++ b/src/extensions/WorkflowCore.WebAPI/ServiceCollectionExtensions.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; namespace Microsoft.Extensions.DependencyInjection { diff --git a/src/providers/WorkflowCore.LockProviders.SqlServer/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.LockProviders.SqlServer/ServiceCollectionExtensions.cs index e93985658..1bdcab46c 100644 --- a/src/providers/WorkflowCore.LockProviders.SqlServer/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.LockProviders.SqlServer/ServiceCollectionExtensions.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using Microsoft.Extensions.Logging; using WorkflowCore.LockProviders.SqlServer; using WorkflowCore.Models; diff --git a/src/providers/WorkflowCore.LockProviders.SqlServer/SqlLockProvider.cs b/src/providers/WorkflowCore.LockProviders.SqlServer/SqlLockProvider.cs index cfeafd36c..92795d871 100644 --- a/src/providers/WorkflowCore.LockProviders.SqlServer/SqlLockProvider.cs +++ b/src/providers/WorkflowCore.LockProviders.SqlServer/SqlLockProvider.cs @@ -5,7 +5,6 @@ using WorkflowCore.Interface; using System.Data; using System.Collections.Generic; -using System.Collections.Concurrent; using System.Threading; namespace WorkflowCore.LockProviders.SqlServer diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs index ae0659968..c978131d1 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Models; using WorkflowCore.Persistence.EntityFramework.Models; diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Interfaces/IWorkflowDbContextFactory.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Interfaces/IWorkflowDbContextFactory.cs index 574f9c39f..61dfb5214 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Interfaces/IWorkflowDbContextFactory.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Interfaces/IWorkflowDbContextFactory.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Persistence.EntityFramework.Services; namespace WorkflowCore.Persistence.EntityFramework.Interfaces diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedEvent.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedEvent.cs index d60090c83..832bee16b 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedEvent.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedEvent.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -using System.Threading.Tasks; namespace WorkflowCore.Persistence.EntityFramework.Models { diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExecutionError.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExecutionError.cs index 1a181a821..7741aa767 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExecutionError.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExecutionError.cs @@ -1,10 +1,6 @@ using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; using System.Linq; -using System.Threading.Tasks; -using WorkflowCore.Models; namespace WorkflowCore.Persistence.EntityFramework.Models { diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExecutionPointer.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExecutionPointer.cs index 984e27735..c7b5b48eb 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExecutionPointer.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExecutionPointer.cs @@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Models; namespace WorkflowCore.Persistence.EntityFramework.Models diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExecutionPointerCollection.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExecutionPointerCollection.cs index c8950803b..cbff64146 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExecutionPointerCollection.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExecutionPointerCollection.cs @@ -1,7 +1,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Persistence.EntityFramework.Models { diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExtensionAttribute.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExtensionAttribute.cs index 3786e9e5a..5a382d8a1 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExtensionAttribute.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedExtensionAttribute.cs @@ -1,10 +1,7 @@ using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; -using System.Threading.Tasks; -using WorkflowCore.Models; namespace WorkflowCore.Persistence.EntityFramework.Models { diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedSubscription.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedSubscription.cs index f8fe0cca0..fcc10f005 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedSubscription.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedSubscription.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; using System.Linq; -using System.Threading.Tasks; namespace WorkflowCore.Persistence.EntityFramework.Models { diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedWorkflow.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedWorkflow.cs index b212bc0c9..5c427a988 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedWorkflow.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedWorkflow.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Models; namespace WorkflowCore.Persistence.EntityFramework.Models diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Properties/AssemblyInfo.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Properties/AssemblyInfo.cs index 9371ecd66..d147caeeb 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Properties/AssemblyInfo.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs index 3af7354de..a616dda01 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs @@ -2,14 +2,10 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.Extensions.DependencyInjection; using WorkflowCore.Interface; using WorkflowCore.Persistence.EntityFramework.Models; using WorkflowCore.Models; -using Microsoft.EntityFrameworkCore.Metadata.Builders; using WorkflowCore.Persistence.EntityFramework.Interfaces; namespace WorkflowCore.Persistence.EntityFramework.Services diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs index 69f83cf96..7b80db3da 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs @@ -1,13 +1,7 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -using WorkflowCore.Interface; -using WorkflowCore.Models; using WorkflowCore.Persistence.EntityFramework.Models; namespace WorkflowCore.Persistence.EntityFramework.Services diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/ConfigOptions.cs b/src/providers/WorkflowCore.Persistence.MongoDB/ConfigOptions.cs index c5b9cddbd..0efd90b42 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/ConfigOptions.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/ConfigOptions.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; namespace WorkflowCore.Persistence.MongoDB { diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Properties/AssemblyInfo.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Properties/AssemblyInfo.cs index df8354da4..4c1a32df7 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Properties/AssemblyInfo.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Persistence.MongoDB/ServiceCollectionExtensions.cs index a5d3ebb5c..34e7857c8 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/ServiceCollectionExtensions.cs @@ -1,8 +1,6 @@ using MongoDB.Driver; using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Persistence.MongoDB.Services; diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/AssemblyQualifiedDiscriminatorConvention.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/AssemblyQualifiedDiscriminatorConvention.cs index 64908727e..b9845f6f8 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/AssemblyQualifiedDiscriminatorConvention.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/AssemblyQualifiedDiscriminatorConvention.cs @@ -1,8 +1,6 @@ using MongoDB.Bson.Serialization.Conventions; using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using MongoDB.Bson; using MongoDB.Bson.IO; diff --git a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs index 17a84e5d7..c72c16199 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs @@ -2,8 +2,6 @@ using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using WorkflowCore.Persistence.MySQL; namespace WorkflowCore.Persistence.MySQL.Migrations { diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170126230815_InitialDatabase.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170126230815_InitialDatabase.cs index c6f6d73f3..c74d0e6f1 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170126230815_InitialDatabase.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170126230815_InitialDatabase.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170312161610_Events.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170312161610_Events.cs index 77fc5a589..6be6f105b 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170312161610_Events.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170312161610_Events.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170507214430_ControlStructures.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170507214430_ControlStructures.cs index 8e44ba8aa..ddbe6630a 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170507214430_ControlStructures.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170507214430_ControlStructures.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Migrations; namespace WorkflowCore.Persistence.PostgreSQL.Migrations diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170519231452_PersistOutcome.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170519231452_PersistOutcome.cs index 4a5806080..0544d31e5 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170519231452_PersistOutcome.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170519231452_PersistOutcome.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Migrations; namespace WorkflowCore.Persistence.PostgreSQL.Migrations diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170722200412_WfReference.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170722200412_WfReference.cs index 997299d80..a7058ff61 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170722200412_WfReference.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20170722200412_WfReference.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Migrations; namespace WorkflowCore.Persistence.PostgreSQL.Migrations diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20171223020844_StepScope.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20171223020844_StepScope.cs index 439bfd655..023ca1919 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20171223020844_StepScope.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20171223020844_StepScope.cs @@ -1,6 +1,5 @@ using Microsoft.EntityFrameworkCore.Migrations; using System; -using System.Collections.Generic; namespace WorkflowCore.Persistence.PostgreSQL.Migrations { diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs index 71ab82c32..6def22497 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs @@ -2,9 +2,7 @@ using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using WorkflowCore.Persistence.PostgreSQL; namespace WorkflowCore.Persistence.PostgreSQL.Migrations { diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContext.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContext.cs index 818a75be2..17e83e958 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContext.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContext.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using WorkflowCore.Persistence.EntityFramework.Models; diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContextFactory.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContextFactory.cs index e0758dfab..98a633e1d 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContextFactory.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContextFactory.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Persistence.EntityFramework.Interfaces; using WorkflowCore.Persistence.EntityFramework.Services; diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Properties/AssemblyInfo.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Properties/AssemblyInfo.cs index 036cf6f38..01280515a 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Properties/AssemblyInfo.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/ServiceCollectionExtensions.cs index 8df41c092..9366c3936 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/ServiceCollectionExtensions.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Persistence.EntityFramework.Services; diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/RavenStoreOptions.cs b/src/providers/WorkflowCore.Persistence.RavenDB/RavenStoreOptions.cs index 00a420668..9208e0ce1 100644 --- a/src/providers/WorkflowCore.Persistence.RavenDB/RavenStoreOptions.cs +++ b/src/providers/WorkflowCore.Persistence.RavenDB/RavenStoreOptions.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Persistence.RavenDB { diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Persistence.RavenDB/ServiceCollectionExtensions.cs index 4b7d12926..fb05b9ba3 100644 --- a/src/providers/WorkflowCore.Persistence.RavenDB/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Persistence.RavenDB/ServiceCollectionExtensions.cs @@ -1,9 +1,5 @@ -using Raven.Client.Documents.Operations; -using System; -using System.Collections.Generic; -using System.Text; +using System; using WorkflowCore.Models; -using Raven.Client; using Raven.Client.Documents; using System.Security.Cryptography.X509Certificates; using WorkflowCore.Persistence.RavenDB.Services; diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavenDbIndexes.cs b/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavenDbIndexes.cs index 75f5ab106..77b4dbae5 100644 --- a/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavenDbIndexes.cs +++ b/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavenDbIndexes.cs @@ -1,7 +1,5 @@ using Raven.Client.Documents.Indexes; using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Models; namespace WorkflowCore.Persistence.RavenDB.Services diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs index 66d38b5aa..7d1f87ddd 100644 --- a/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs @@ -1,5 +1,4 @@ using Raven.Client.Documents; -using Raven.Client.Documents.Indexes; using Raven.Client.Documents.Linq; using Raven.Client.Documents.Operations; using System; diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/Services/WorkflowPurger.cs b/src/providers/WorkflowCore.Persistence.RavenDB/Services/WorkflowPurger.cs index 70fd0210b..f799fd6a5 100644 --- a/src/providers/WorkflowCore.Persistence.RavenDB/Services/WorkflowPurger.cs +++ b/src/providers/WorkflowCore.Persistence.RavenDB/Services/WorkflowPurger.cs @@ -1,13 +1,9 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; -using Raven.Client; using System.Threading.Tasks; using Raven.Client.Documents; using System.Linq; -using Raven.Client.Extensions; using Raven.Client.Documents.Operations; using Raven.Client.Documents.Queries; diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170126230839_InitialDatabase.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170126230839_InitialDatabase.cs index 12153905d..cc13adb32 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170126230839_InitialDatabase.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170126230839_InitialDatabase.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Metadata; diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170312161610_Events.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170312161610_Events.cs index bc4565904..c3854150f 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170312161610_Events.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170312161610_Events.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Metadata; diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170507214430_ControlStructures.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170507214430_ControlStructures.cs index 18e8c5b38..df0f88ab3 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170507214430_ControlStructures.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170507214430_ControlStructures.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Migrations; namespace WorkflowCore.Persistence.SqlServer.Migrations diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170519231452_PersistOutcome.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170519231452_PersistOutcome.cs index b4fd690ae..dd472520e 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170519231452_PersistOutcome.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170519231452_PersistOutcome.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Migrations; namespace WorkflowCore.Persistence.SqlServer.Migrations diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170722195832_WfReference.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170722195832_WfReference.cs index 1e94cad6d..285e7d944 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170722195832_WfReference.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20170722195832_WfReference.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Migrations; namespace WorkflowCore.Persistence.SqlServer.Migrations diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20171223020645_StepScope.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20171223020645_StepScope.cs index e9ff500e1..c7e1e4ec6 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20171223020645_StepScope.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20171223020645_StepScope.cs @@ -1,6 +1,5 @@ using Microsoft.EntityFrameworkCore.Migrations; using System; -using System.Collections.Generic; namespace WorkflowCore.Persistence.SqlServer.Migrations { diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs index 1b5c63cc1..2e32d838d 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs @@ -2,9 +2,6 @@ using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using WorkflowCore.Persistence.SqlServer; namespace WorkflowCore.Persistence.SqlServer.Migrations { diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Properties/AssemblyInfo.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Properties/AssemblyInfo.cs index afdd6ce15..26131f807 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Properties/AssemblyInfo.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Persistence.SqlServer/ServiceCollectionExtensions.cs index 009f1edb7..0a54b1ea2 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/ServiceCollectionExtensions.cs @@ -2,7 +2,6 @@ using System.Data.Common; using WorkflowCore.Interface; using WorkflowCore.Models; -using WorkflowCore.Persistence.EntityFramework.Interfaces; using WorkflowCore.Persistence.EntityFramework.Services; using WorkflowCore.Persistence.SqlServer; diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/SqlContextFactory.cs b/src/providers/WorkflowCore.Persistence.SqlServer/SqlContextFactory.cs index 8cb6d57a8..066aae73f 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/SqlContextFactory.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/SqlContextFactory.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Data.Common; using Microsoft.EntityFrameworkCore; using WorkflowCore.Persistence.EntityFramework.Interfaces; diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs b/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs index 7383cce3e..6e2656a5b 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using WorkflowCore.Persistence.EntityFramework.Models; diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/Properties/AssemblyInfo.cs b/src/providers/WorkflowCore.Persistence.Sqlite/Properties/AssemblyInfo.cs index 02fd59231..04f04aacc 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/Properties/AssemblyInfo.cs +++ b/src/providers/WorkflowCore.Persistence.Sqlite/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Persistence.Sqlite/ServiceCollectionExtensions.cs index f137c33b5..0d5dd5a8e 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Persistence.Sqlite/ServiceCollectionExtensions.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Persistence.EntityFramework.Services; diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/SqliteContext.cs b/src/providers/WorkflowCore.Persistence.Sqlite/SqliteContext.cs index 7a9737c4e..1b5a6c469 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/SqliteContext.cs +++ b/src/providers/WorkflowCore.Persistence.Sqlite/SqliteContext.cs @@ -1,9 +1,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Persistence.EntityFramework.Models; using WorkflowCore.Persistence.EntityFramework.Services; diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/SqliteContextFactory.cs b/src/providers/WorkflowCore.Persistence.Sqlite/SqliteContextFactory.cs index 94c9e4df8..9d24d688c 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/SqliteContextFactory.cs +++ b/src/providers/WorkflowCore.Persistence.Sqlite/SqliteContextFactory.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Persistence.EntityFramework.Interfaces; using WorkflowCore.Persistence.EntityFramework.Services; diff --git a/src/providers/WorkflowCore.Providers.AWS/Interface/IKinesisStreamConsumer.cs b/src/providers/WorkflowCore.Providers.AWS/Interface/IKinesisStreamConsumer.cs index 41e48b013..d4d66614f 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Interface/IKinesisStreamConsumer.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Interface/IKinesisStreamConsumer.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; using Amazon.Kinesis.Model; diff --git a/src/providers/WorkflowCore.Providers.AWS/Interface/IKinesisTracker.cs b/src/providers/WorkflowCore.Providers.AWS/Interface/IKinesisTracker.cs index 3a4cee3a0..f3cb37510 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Interface/IKinesisTracker.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Interface/IKinesisTracker.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; namespace WorkflowCore.Providers.AWS.Interface diff --git a/src/providers/WorkflowCore.Providers.AWS/ModelExtensions.cs b/src/providers/WorkflowCore.Providers.AWS/ModelExtensions.cs index 62f9cf38e..daf5b6889 100644 --- a/src/providers/WorkflowCore.Providers.AWS/ModelExtensions.cs +++ b/src/providers/WorkflowCore.Providers.AWS/ModelExtensions.cs @@ -1,11 +1,8 @@ using Amazon.DynamoDBv2.Model; -using Amazon.Util; using System; using System.Collections.Generic; using System.Linq; -using System.Text; using Newtonsoft.Json; -using Newtonsoft.Json.Bson; using WorkflowCore.Models; namespace WorkflowCore.Providers.AWS diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs index a6bb72662..3f381c8c3 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs @@ -4,7 +4,6 @@ using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; using WorkflowCore.Providers.AWS.Interface; diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs index 69ba8eaf1..6c27546ab 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; using WorkflowCore.Providers.AWS.Interface; using WorkflowCore.Interface; diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisProvider.cs index 5b0830ce0..99d43d94f 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisProvider.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Text; using System.Threading.Tasks; using Amazon; using Amazon.Kinesis; diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisTracker.cs b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisTracker.cs index 8d6a04b8e..9c5548420 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisTracker.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisTracker.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; -using System.Threading; using System.Threading.Tasks; using Amazon; using Amazon.DynamoDBv2; diff --git a/src/providers/WorkflowCore.Providers.Azure/Models/ControlledLock.cs b/src/providers/WorkflowCore.Providers.Azure/Models/ControlledLock.cs index f32a1b0cd..5b0343456 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Models/ControlledLock.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Models/ControlledLock.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.WindowsAzure.Storage.Blob; namespace WorkflowCore.Providers.Azure.Models diff --git a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedEvent.cs b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedEvent.cs index 85579f7fc..57e43fd40 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedEvent.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedEvent.cs @@ -1,6 +1,5 @@ using Newtonsoft.Json; using System; -using System.Collections.Generic; using WorkflowCore.Models; namespace WorkflowCore.Providers.Azure.Models diff --git a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedSubscription.cs b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedSubscription.cs index 55482e17d..d1966eea6 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedSubscription.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedSubscription.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Newtonsoft.Json; using WorkflowCore.Models; diff --git a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedWorkflow.cs b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedWorkflow.cs index bd480fb71..f8af8228d 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Models/PersistedWorkflow.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Models/PersistedWorkflow.cs @@ -1,6 +1,5 @@ using Newtonsoft.Json; using System; -using System.Collections.Generic; using WorkflowCore.Models; namespace WorkflowCore.Providers.Azure.Models diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs b/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs index 9b6d0bdb1..c52e823c7 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/AzureStorageQueueProvider.cs b/src/providers/WorkflowCore.Providers.Azure/Services/AzureStorageQueueProvider.cs index 5b104ab30..cbd76d1f7 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/AzureStorageQueueProvider.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/AzureStorageQueueProvider.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs index 8ca697fc2..a30ca8f27 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; using Microsoft.Azure.Cosmos; using WorkflowCore.Interface; diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs index ff1c2e187..ab86cc3f6 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.ObjectModel; using System.Threading.Tasks; using Microsoft.Azure.Cosmos; using Microsoft.Extensions.Logging; diff --git a/src/providers/WorkflowCore.Providers.Elasticsearch/Services/ElasticsearchIndexer.cs b/src/providers/WorkflowCore.Providers.Elasticsearch/Services/ElasticsearchIndexer.cs index 21e285207..8195bd53a 100644 --- a/src/providers/WorkflowCore.Providers.Elasticsearch/Services/ElasticsearchIndexer.cs +++ b/src/providers/WorkflowCore.Providers.Elasticsearch/Services/ElasticsearchIndexer.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using System.Reflection; using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/providers/WorkflowCore.Providers.Redis/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.Redis/ServiceCollectionExtensions.cs index ccc96a98c..514ba21a3 100644 --- a/src/providers/WorkflowCore.Providers.Redis/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.Redis/ServiceCollectionExtensions.cs @@ -1,6 +1,5 @@ using System; using Microsoft.Extensions.Logging; -using StackExchange.Redis; using WorkflowCore.Models; using WorkflowCore.Providers.Redis.Services; diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisLifeCycleEventHub.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisLifeCycleEventHub.cs index 2cf12e1cc..bb595309d 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisLifeCycleEventHub.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisLifeCycleEventHub.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Newtonsoft.Json; diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisLockProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisLockProvider.cs index 006f531d6..469ca2763 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisLockProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisLockProvider.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs index 66ca58d72..4c26b38b2 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Newtonsoft.Json; diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisQueueProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisQueueProvider.cs index 1281bfbdf..460f3d741 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisQueueProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisQueueProvider.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Properties/AssemblyInfo.cs b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Properties/AssemblyInfo.cs index 4a1926468..53e1beb8e 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Properties/AssemblyInfo.cs +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs index 8a84f99c6..64322ad50 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs @@ -1,15 +1,12 @@ using Newtonsoft.Json; using RabbitMQ.Client; -using RabbitMQ.Client.Events; using System; -using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.Interface; -using WorkflowCore.Models; using WorkflowCore.QueueProviders.RabbitMQ.Interfaces; namespace WorkflowCore.QueueProviders.RabbitMQ.Services diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/Interfaces/ISqlServerQueueProviderMigrator.cs b/src/providers/WorkflowCore.QueueProviders.SqlServer/Interfaces/ISqlServerQueueProviderMigrator.cs index 50f1173e1..19b173d5c 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/Interfaces/ISqlServerQueueProviderMigrator.cs +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/Interfaces/ISqlServerQueueProviderMigrator.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; namespace WorkflowCore.QueueProviders.SqlServer.Interfaces diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/Models/QueueConfig.cs b/src/providers/WorkflowCore.QueueProviders.SqlServer/Models/QueueConfig.cs index 1915f487c..c323b9d03 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/Models/QueueConfig.cs +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/Models/QueueConfig.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.QueueProviders.SqlServer.Models { diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.QueueProviders.SqlServer/ServiceCollectionExtensions.cs index ada9b580a..56f4f7fc2 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/ServiceCollectionExtensions.cs @@ -1,8 +1,6 @@ #region using using System; -using Microsoft.Extensions.DependencyInjection; - using WorkflowCore.Models; using WorkflowCore.QueueProviders.SqlServer; using WorkflowCore.QueueProviders.SqlServer.Interfaces; diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/QueueConfigProvider.cs b/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/QueueConfigProvider.cs index 9e54393a1..4cbcd7dac 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/QueueConfigProvider.cs +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/QueueConfigProvider.cs @@ -1,7 +1,6 @@ #region using using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using WorkflowCore.Interface; diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/SqlCommandExecutor.cs b/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/SqlCommandExecutor.cs index 3ff92713d..5c77342fe 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/SqlCommandExecutor.cs +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/SqlCommandExecutor.cs @@ -1,8 +1,6 @@ #region using using System; -using System.Collections.Generic; -using System.Data; using System.Data.Common; using System.Data.SqlClient; using System.Linq; diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/SqlServerQueueProviderMigrator.cs b/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/SqlServerQueueProviderMigrator.cs index a28f894e6..18a27b920 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/SqlServerQueueProviderMigrator.cs +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/Services/SqlServerQueueProviderMigrator.cs @@ -3,7 +3,6 @@ using System; using System.Data.SqlClient; using System.Linq; -using System.Text.RegularExpressions; using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.QueueProviders.SqlServer.Interfaces; diff --git a/src/samples/WorkflowCore.Sample01/HelloWorldWorkflow.cs b/src/samples/WorkflowCore.Sample01/HelloWorldWorkflow.cs index 74887e1e5..f268b6307 100644 --- a/src/samples/WorkflowCore.Sample01/HelloWorldWorkflow.cs +++ b/src/samples/WorkflowCore.Sample01/HelloWorldWorkflow.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; -using WorkflowCore.Models; using WorkflowCore.Sample01.Steps; namespace WorkflowCore.Sample01 diff --git a/src/samples/WorkflowCore.Sample01/Program.cs b/src/samples/WorkflowCore.Sample01/Program.cs index c25838dbe..6577f5ba0 100644 --- a/src/samples/WorkflowCore.Sample01/Program.cs +++ b/src/samples/WorkflowCore.Sample01/Program.cs @@ -1,12 +1,8 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Sample01.Steps; -using WorkflowCore.Services; namespace WorkflowCore.Sample01 { diff --git a/src/samples/WorkflowCore.Sample01/Properties/AssemblyInfo.cs b/src/samples/WorkflowCore.Sample01/Properties/AssemblyInfo.cs index 32a0f2b49..be2722eae 100644 --- a/src/samples/WorkflowCore.Sample01/Properties/AssemblyInfo.cs +++ b/src/samples/WorkflowCore.Sample01/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/samples/WorkflowCore.Sample01/Steps/GoodbyeWorld.cs b/src/samples/WorkflowCore.Sample01/Steps/GoodbyeWorld.cs index 8c94778f7..048b57bb1 100644 --- a/src/samples/WorkflowCore.Sample01/Steps/GoodbyeWorld.cs +++ b/src/samples/WorkflowCore.Sample01/Steps/GoodbyeWorld.cs @@ -1,8 +1,6 @@ using Microsoft.Extensions.Logging; using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample01/Steps/HelloWorld.cs b/src/samples/WorkflowCore.Sample01/Steps/HelloWorld.cs index a5a09534a..415ad08f2 100644 --- a/src/samples/WorkflowCore.Sample01/Steps/HelloWorld.cs +++ b/src/samples/WorkflowCore.Sample01/Steps/HelloWorld.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample02/Program.cs b/src/samples/WorkflowCore.Sample02/Program.cs index 3c1a65bcf..22dd3c196 100644 --- a/src/samples/WorkflowCore.Sample02/Program.cs +++ b/src/samples/WorkflowCore.Sample02/Program.cs @@ -1,11 +1,7 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; -using WorkflowCore.Services; namespace WorkflowCore.Sample02 diff --git a/src/samples/WorkflowCore.Sample02/Properties/AssemblyInfo.cs b/src/samples/WorkflowCore.Sample02/Properties/AssemblyInfo.cs index 5b02eba4c..f677ae82a 100644 --- a/src/samples/WorkflowCore.Sample02/Properties/AssemblyInfo.cs +++ b/src/samples/WorkflowCore.Sample02/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/samples/WorkflowCore.Sample02/SimpleDecisionWorkflow.cs b/src/samples/WorkflowCore.Sample02/SimpleDecisionWorkflow.cs index b32fa3c55..91a0323f2 100644 --- a/src/samples/WorkflowCore.Sample02/SimpleDecisionWorkflow.cs +++ b/src/samples/WorkflowCore.Sample02/SimpleDecisionWorkflow.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Sample02.Steps; diff --git a/src/samples/WorkflowCore.Sample02/Steps/CustomMessage.cs b/src/samples/WorkflowCore.Sample02/Steps/CustomMessage.cs index 2514a7384..efb3fb662 100644 --- a/src/samples/WorkflowCore.Sample02/Steps/CustomMessage.cs +++ b/src/samples/WorkflowCore.Sample02/Steps/CustomMessage.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample02/Steps/GoodbyeWorld.cs b/src/samples/WorkflowCore.Sample02/Steps/GoodbyeWorld.cs index 8e09fed44..c082e57c9 100644 --- a/src/samples/WorkflowCore.Sample02/Steps/GoodbyeWorld.cs +++ b/src/samples/WorkflowCore.Sample02/Steps/GoodbyeWorld.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample02/Steps/HelloWorld.cs b/src/samples/WorkflowCore.Sample02/Steps/HelloWorld.cs index 151d92a3e..884b01525 100644 --- a/src/samples/WorkflowCore.Sample02/Steps/HelloWorld.cs +++ b/src/samples/WorkflowCore.Sample02/Steps/HelloWorld.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample02/Steps/RandomOutput.cs b/src/samples/WorkflowCore.Sample02/Steps/RandomOutput.cs index 90bbdbddf..80c285161 100644 --- a/src/samples/WorkflowCore.Sample02/Steps/RandomOutput.cs +++ b/src/samples/WorkflowCore.Sample02/Steps/RandomOutput.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample03/MyDataClass.cs b/src/samples/WorkflowCore.Sample03/MyDataClass.cs index a3b51429c..3f0cead60 100644 --- a/src/samples/WorkflowCore.Sample03/MyDataClass.cs +++ b/src/samples/WorkflowCore.Sample03/MyDataClass.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; -using WorkflowCore.Interface; namespace WorkflowCore.Sample03 { diff --git a/src/samples/WorkflowCore.Sample03/PassingDataWorkflow.cs b/src/samples/WorkflowCore.Sample03/PassingDataWorkflow.cs index c96f3dc03..56307b42e 100644 --- a/src/samples/WorkflowCore.Sample03/PassingDataWorkflow.cs +++ b/src/samples/WorkflowCore.Sample03/PassingDataWorkflow.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Sample03.Steps; diff --git a/src/samples/WorkflowCore.Sample03/Program.cs b/src/samples/WorkflowCore.Sample03/Program.cs index 96c06d45d..813e5dfd7 100644 --- a/src/samples/WorkflowCore.Sample03/Program.cs +++ b/src/samples/WorkflowCore.Sample03/Program.cs @@ -1,12 +1,8 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Debug; using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; -using WorkflowCore.Services; namespace WorkflowCore.Sample03 diff --git a/src/samples/WorkflowCore.Sample03/Properties/AssemblyInfo.cs b/src/samples/WorkflowCore.Sample03/Properties/AssemblyInfo.cs index 324e13bc7..3965ce4cd 100644 --- a/src/samples/WorkflowCore.Sample03/Properties/AssemblyInfo.cs +++ b/src/samples/WorkflowCore.Sample03/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/samples/WorkflowCore.Sample03/Steps/AddNumbers.cs b/src/samples/WorkflowCore.Sample03/Steps/AddNumbers.cs index 209229812..a8209d227 100644 --- a/src/samples/WorkflowCore.Sample03/Steps/AddNumbers.cs +++ b/src/samples/WorkflowCore.Sample03/Steps/AddNumbers.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using WorkflowCore.Interface; diff --git a/src/samples/WorkflowCore.Sample03/Steps/CustomMessage.cs b/src/samples/WorkflowCore.Sample03/Steps/CustomMessage.cs index ce83fcdc0..810092b30 100644 --- a/src/samples/WorkflowCore.Sample03/Steps/CustomMessage.cs +++ b/src/samples/WorkflowCore.Sample03/Steps/CustomMessage.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample03/Steps/GoodbyeWorld.cs b/src/samples/WorkflowCore.Sample03/Steps/GoodbyeWorld.cs index 4a700c768..c7f985288 100644 --- a/src/samples/WorkflowCore.Sample03/Steps/GoodbyeWorld.cs +++ b/src/samples/WorkflowCore.Sample03/Steps/GoodbyeWorld.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample03/Steps/HelloWorld.cs b/src/samples/WorkflowCore.Sample03/Steps/HelloWorld.cs index ccd93045c..e156b13ba 100644 --- a/src/samples/WorkflowCore.Sample03/Steps/HelloWorld.cs +++ b/src/samples/WorkflowCore.Sample03/Steps/HelloWorld.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample04/EventSampleWorkflow.cs b/src/samples/WorkflowCore.Sample04/EventSampleWorkflow.cs index d07a5ac03..b78eaa751 100644 --- a/src/samples/WorkflowCore.Sample04/EventSampleWorkflow.cs +++ b/src/samples/WorkflowCore.Sample04/EventSampleWorkflow.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Sample04.Steps; diff --git a/src/samples/WorkflowCore.Sample04/MyDataClass.cs b/src/samples/WorkflowCore.Sample04/MyDataClass.cs index 0863891a2..719459c33 100644 --- a/src/samples/WorkflowCore.Sample04/MyDataClass.cs +++ b/src/samples/WorkflowCore.Sample04/MyDataClass.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; namespace WorkflowCore.Sample04 { diff --git a/src/samples/WorkflowCore.Sample04/Program.cs b/src/samples/WorkflowCore.Sample04/Program.cs index 09e80b737..0e1895d44 100644 --- a/src/samples/WorkflowCore.Sample04/Program.cs +++ b/src/samples/WorkflowCore.Sample04/Program.cs @@ -1,18 +1,8 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using MongoDB.Driver; using StackExchange.Redis; using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; -using Amazon; -using Amazon.Runtime; using WorkflowCore.Interface; -using WorkflowCore.Persistence.MongoDB.Services; -using WorkflowCore.Services; -using Amazon.DynamoDBv2; -using Amazon.SQS; namespace WorkflowCore.Sample04 { diff --git a/src/samples/WorkflowCore.Sample04/Properties/AssemblyInfo.cs b/src/samples/WorkflowCore.Sample04/Properties/AssemblyInfo.cs index 2bc13d42e..e51bcce10 100644 --- a/src/samples/WorkflowCore.Sample04/Properties/AssemblyInfo.cs +++ b/src/samples/WorkflowCore.Sample04/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/samples/WorkflowCore.Sample04/Steps/CustomMessage.cs b/src/samples/WorkflowCore.Sample04/Steps/CustomMessage.cs index 4d96503fb..678f22731 100644 --- a/src/samples/WorkflowCore.Sample04/Steps/CustomMessage.cs +++ b/src/samples/WorkflowCore.Sample04/Steps/CustomMessage.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample05/DeferSampleWorkflow.cs b/src/samples/WorkflowCore.Sample05/DeferSampleWorkflow.cs index 08380429c..ff9223ae9 100644 --- a/src/samples/WorkflowCore.Sample05/DeferSampleWorkflow.cs +++ b/src/samples/WorkflowCore.Sample05/DeferSampleWorkflow.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Sample05.Steps; diff --git a/src/samples/WorkflowCore.Sample05/Program.cs b/src/samples/WorkflowCore.Sample05/Program.cs index 274e10232..a0e727633 100644 --- a/src/samples/WorkflowCore.Sample05/Program.cs +++ b/src/samples/WorkflowCore.Sample05/Program.cs @@ -1,13 +1,7 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using MongoDB.Driver; using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; -using WorkflowCore.Persistence.MongoDB.Services; -using WorkflowCore.Services; namespace WorkflowCore.Sample05 { diff --git a/src/samples/WorkflowCore.Sample05/Properties/AssemblyInfo.cs b/src/samples/WorkflowCore.Sample05/Properties/AssemblyInfo.cs index 660ed42d2..a510661da 100644 --- a/src/samples/WorkflowCore.Sample05/Properties/AssemblyInfo.cs +++ b/src/samples/WorkflowCore.Sample05/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/samples/WorkflowCore.Sample05/Steps/SleepStep.cs b/src/samples/WorkflowCore.Sample05/Steps/SleepStep.cs index f2d1ef94c..c11cfb6f7 100644 --- a/src/samples/WorkflowCore.Sample05/Steps/SleepStep.cs +++ b/src/samples/WorkflowCore.Sample05/Steps/SleepStep.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample06/MultipleOutcomeWorkflow.cs b/src/samples/WorkflowCore.Sample06/MultipleOutcomeWorkflow.cs index 8b792d968..5f7661455 100644 --- a/src/samples/WorkflowCore.Sample06/MultipleOutcomeWorkflow.cs +++ b/src/samples/WorkflowCore.Sample06/MultipleOutcomeWorkflow.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Sample06.Steps; diff --git a/src/samples/WorkflowCore.Sample06/Program.cs b/src/samples/WorkflowCore.Sample06/Program.cs index ba08aa071..4612f92cc 100644 --- a/src/samples/WorkflowCore.Sample06/Program.cs +++ b/src/samples/WorkflowCore.Sample06/Program.cs @@ -1,13 +1,7 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using MongoDB.Driver; using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; -using WorkflowCore.Persistence.MongoDB.Services; -using WorkflowCore.Services; namespace WorkflowCore.Sample06 { diff --git a/src/samples/WorkflowCore.Sample06/Properties/AssemblyInfo.cs b/src/samples/WorkflowCore.Sample06/Properties/AssemblyInfo.cs index 20a134e87..abc7e334f 100644 --- a/src/samples/WorkflowCore.Sample06/Properties/AssemblyInfo.cs +++ b/src/samples/WorkflowCore.Sample06/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/samples/WorkflowCore.Sample06/Steps/RandomOutput.cs b/src/samples/WorkflowCore.Sample06/Steps/RandomOutput.cs index 79587280d..dc686abec 100644 --- a/src/samples/WorkflowCore.Sample06/Steps/RandomOutput.cs +++ b/src/samples/WorkflowCore.Sample06/Steps/RandomOutput.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample06/Steps/TaskA.cs b/src/samples/WorkflowCore.Sample06/Steps/TaskA.cs index 67d20cf76..17b8cd6d3 100644 --- a/src/samples/WorkflowCore.Sample06/Steps/TaskA.cs +++ b/src/samples/WorkflowCore.Sample06/Steps/TaskA.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample06/Steps/TaskB.cs b/src/samples/WorkflowCore.Sample06/Steps/TaskB.cs index cd2554eae..c230fb836 100644 --- a/src/samples/WorkflowCore.Sample06/Steps/TaskB.cs +++ b/src/samples/WorkflowCore.Sample06/Steps/TaskB.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample06/Steps/TaskC.cs b/src/samples/WorkflowCore.Sample06/Steps/TaskC.cs index 39770f8e4..ec840b843 100644 --- a/src/samples/WorkflowCore.Sample06/Steps/TaskC.cs +++ b/src/samples/WorkflowCore.Sample06/Steps/TaskC.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample06/Steps/TaskD.cs b/src/samples/WorkflowCore.Sample06/Steps/TaskD.cs index 2f40005ea..cd4ff1940 100644 --- a/src/samples/WorkflowCore.Sample06/Steps/TaskD.cs +++ b/src/samples/WorkflowCore.Sample06/Steps/TaskD.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample07/Program.cs b/src/samples/WorkflowCore.Sample07/Program.cs index 57b417b72..b89645580 100644 --- a/src/samples/WorkflowCore.Sample07/Program.cs +++ b/src/samples/WorkflowCore.Sample07/Program.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; -using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; namespace WorkflowCore.Sample07 diff --git a/src/samples/WorkflowCore.Sample07/Startup.cs b/src/samples/WorkflowCore.Sample07/Startup.cs index 42abb05cb..80264f6d2 100644 --- a/src/samples/WorkflowCore.Sample07/Startup.cs +++ b/src/samples/WorkflowCore.Sample07/Startup.cs @@ -1,10 +1,7 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using WorkflowCore.Interface; diff --git a/src/samples/WorkflowCore.Sample08/HumanWorkflow.cs b/src/samples/WorkflowCore.Sample08/HumanWorkflow.cs index b6e00849d..b2b48b1c8 100644 --- a/src/samples/WorkflowCore.Sample08/HumanWorkflow.cs +++ b/src/samples/WorkflowCore.Sample08/HumanWorkflow.cs @@ -1,10 +1,7 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; -using WorkflowCore.Users.Models; namespace WorkflowCore.Sample08 { diff --git a/src/samples/WorkflowCore.Sample08/Program.cs b/src/samples/WorkflowCore.Sample08/Program.cs index 4da29c6b9..970834c88 100644 --- a/src/samples/WorkflowCore.Sample08/Program.cs +++ b/src/samples/WorkflowCore.Sample08/Program.cs @@ -1,10 +1,7 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using System; -using System.Collections.Generic; using System.Linq; using System.Threading; -using System.Threading.Tasks; using WorkflowCore.Interface; namespace WorkflowCore.Sample08 diff --git a/src/samples/WorkflowCore.Sample08/Properties/AssemblyInfo.cs b/src/samples/WorkflowCore.Sample08/Properties/AssemblyInfo.cs index 079de7d9e..2f6266e9f 100644 --- a/src/samples/WorkflowCore.Sample08/Properties/AssemblyInfo.cs +++ b/src/samples/WorkflowCore.Sample08/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/samples/WorkflowCore.Sample09/ForEachWorkflow.cs b/src/samples/WorkflowCore.Sample09/ForEachWorkflow.cs index e9a5cd937..ba462bac1 100644 --- a/src/samples/WorkflowCore.Sample09/ForEachWorkflow.cs +++ b/src/samples/WorkflowCore.Sample09/ForEachWorkflow.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; -using WorkflowCore.Models; namespace WorkflowCore.Sample09 { diff --git a/src/samples/WorkflowCore.Sample09/Program.cs b/src/samples/WorkflowCore.Sample09/Program.cs index 52516fca8..f98fc1547 100644 --- a/src/samples/WorkflowCore.Sample09/Program.cs +++ b/src/samples/WorkflowCore.Sample09/Program.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using System; using WorkflowCore.Interface; diff --git a/src/samples/WorkflowCore.Sample09/Steps/DisplayContext.cs b/src/samples/WorkflowCore.Sample09/Steps/DisplayContext.cs index 9782a32bc..0d9815038 100644 --- a/src/samples/WorkflowCore.Sample09/Steps/DisplayContext.cs +++ b/src/samples/WorkflowCore.Sample09/Steps/DisplayContext.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample09/Steps/DoSomething.cs b/src/samples/WorkflowCore.Sample09/Steps/DoSomething.cs index 57d0f556a..9636c486c 100644 --- a/src/samples/WorkflowCore.Sample09/Steps/DoSomething.cs +++ b/src/samples/WorkflowCore.Sample09/Steps/DoSomething.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample09/Steps/SayGoodbye.cs b/src/samples/WorkflowCore.Sample09/Steps/SayGoodbye.cs index 9836d5f44..c3aaec908 100644 --- a/src/samples/WorkflowCore.Sample09/Steps/SayGoodbye.cs +++ b/src/samples/WorkflowCore.Sample09/Steps/SayGoodbye.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample09/Steps/SayHello.cs b/src/samples/WorkflowCore.Sample09/Steps/SayHello.cs index 94ba8768a..653b28af1 100644 --- a/src/samples/WorkflowCore.Sample09/Steps/SayHello.cs +++ b/src/samples/WorkflowCore.Sample09/Steps/SayHello.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample09s/ForEachSyncWorkflow.cs b/src/samples/WorkflowCore.Sample09s/ForEachSyncWorkflow.cs index 879156d06..2c1a335a7 100644 --- a/src/samples/WorkflowCore.Sample09s/ForEachSyncWorkflow.cs +++ b/src/samples/WorkflowCore.Sample09s/ForEachSyncWorkflow.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; -using WorkflowCore.Models; namespace WorkflowCore.Sample09s { diff --git a/src/samples/WorkflowCore.Sample09s/Program.cs b/src/samples/WorkflowCore.Sample09s/Program.cs index 9fd4dcb0f..09e04abb8 100644 --- a/src/samples/WorkflowCore.Sample09s/Program.cs +++ b/src/samples/WorkflowCore.Sample09s/Program.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using System; using WorkflowCore.Interface; diff --git a/src/samples/WorkflowCore.Sample09s/Steps/DisplayContext.cs b/src/samples/WorkflowCore.Sample09s/Steps/DisplayContext.cs index d7ef216b3..012cda0c6 100644 --- a/src/samples/WorkflowCore.Sample09s/Steps/DisplayContext.cs +++ b/src/samples/WorkflowCore.Sample09s/Steps/DisplayContext.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample09s/Steps/DoSomething.cs b/src/samples/WorkflowCore.Sample09s/Steps/DoSomething.cs index 39344b389..859a13eab 100644 --- a/src/samples/WorkflowCore.Sample09s/Steps/DoSomething.cs +++ b/src/samples/WorkflowCore.Sample09s/Steps/DoSomething.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample09s/Steps/SayGoodbye.cs b/src/samples/WorkflowCore.Sample09s/Steps/SayGoodbye.cs index 34c74103b..1789b74b2 100644 --- a/src/samples/WorkflowCore.Sample09s/Steps/SayGoodbye.cs +++ b/src/samples/WorkflowCore.Sample09s/Steps/SayGoodbye.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample09s/Steps/SayHello.cs b/src/samples/WorkflowCore.Sample09s/Steps/SayHello.cs index 1597910f5..ebec30eed 100644 --- a/src/samples/WorkflowCore.Sample09s/Steps/SayHello.cs +++ b/src/samples/WorkflowCore.Sample09s/Steps/SayHello.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample10/Program.cs b/src/samples/WorkflowCore.Sample10/Program.cs index aa401baa2..5fa612f8e 100644 --- a/src/samples/WorkflowCore.Sample10/Program.cs +++ b/src/samples/WorkflowCore.Sample10/Program.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using System; using WorkflowCore.Interface; diff --git a/src/samples/WorkflowCore.Sample10/Steps/DoSomething.cs b/src/samples/WorkflowCore.Sample10/Steps/DoSomething.cs index 646b929a6..389bd86e3 100644 --- a/src/samples/WorkflowCore.Sample10/Steps/DoSomething.cs +++ b/src/samples/WorkflowCore.Sample10/Steps/DoSomething.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample10/Steps/IncrementStep.cs b/src/samples/WorkflowCore.Sample10/Steps/IncrementStep.cs index cb7177bba..2e000956c 100644 --- a/src/samples/WorkflowCore.Sample10/Steps/IncrementStep.cs +++ b/src/samples/WorkflowCore.Sample10/Steps/IncrementStep.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample10/Steps/SayGoodbye.cs b/src/samples/WorkflowCore.Sample10/Steps/SayGoodbye.cs index 48ec493ef..f28c50dcf 100644 --- a/src/samples/WorkflowCore.Sample10/Steps/SayGoodbye.cs +++ b/src/samples/WorkflowCore.Sample10/Steps/SayGoodbye.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample10/Steps/SayHello.cs b/src/samples/WorkflowCore.Sample10/Steps/SayHello.cs index d0e96745b..0b552ea83 100644 --- a/src/samples/WorkflowCore.Sample10/Steps/SayHello.cs +++ b/src/samples/WorkflowCore.Sample10/Steps/SayHello.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample10/WhileWorkflow.cs b/src/samples/WorkflowCore.Sample10/WhileWorkflow.cs index b65156edc..bf4ce8ccc 100644 --- a/src/samples/WorkflowCore.Sample10/WhileWorkflow.cs +++ b/src/samples/WorkflowCore.Sample10/WhileWorkflow.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; -using WorkflowCore.Models; namespace WorkflowCore.Sample10 { diff --git a/src/samples/WorkflowCore.Sample11/IfWorkflow.cs b/src/samples/WorkflowCore.Sample11/IfWorkflow.cs index 64b31fb56..2b9ef2265 100644 --- a/src/samples/WorkflowCore.Sample11/IfWorkflow.cs +++ b/src/samples/WorkflowCore.Sample11/IfWorkflow.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; -using WorkflowCore.Models; namespace WorkflowCore.Sample11 { diff --git a/src/samples/WorkflowCore.Sample11/Program.cs b/src/samples/WorkflowCore.Sample11/Program.cs index e409b400a..ea920b195 100644 --- a/src/samples/WorkflowCore.Sample11/Program.cs +++ b/src/samples/WorkflowCore.Sample11/Program.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using System; using WorkflowCore.Interface; diff --git a/src/samples/WorkflowCore.Sample11/Steps/PrintMessage.cs b/src/samples/WorkflowCore.Sample11/Steps/PrintMessage.cs index d2f1e013c..16e709773 100644 --- a/src/samples/WorkflowCore.Sample11/Steps/PrintMessage.cs +++ b/src/samples/WorkflowCore.Sample11/Steps/PrintMessage.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample11/Steps/SayGoodbye.cs b/src/samples/WorkflowCore.Sample11/Steps/SayGoodbye.cs index ba7601881..388f5acbf 100644 --- a/src/samples/WorkflowCore.Sample11/Steps/SayGoodbye.cs +++ b/src/samples/WorkflowCore.Sample11/Steps/SayGoodbye.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample11/Steps/SayHello.cs b/src/samples/WorkflowCore.Sample11/Steps/SayHello.cs index b8b5f0ad3..ed5c2a17d 100644 --- a/src/samples/WorkflowCore.Sample11/Steps/SayHello.cs +++ b/src/samples/WorkflowCore.Sample11/Steps/SayHello.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample12/OutcomeWorkflow.cs b/src/samples/WorkflowCore.Sample12/OutcomeWorkflow.cs index 61f1f98cd..aa58e0a74 100644 --- a/src/samples/WorkflowCore.Sample12/OutcomeWorkflow.cs +++ b/src/samples/WorkflowCore.Sample12/OutcomeWorkflow.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; -using WorkflowCore.Models; namespace WorkflowCore.Sample12 { diff --git a/src/samples/WorkflowCore.Sample12/Program.cs b/src/samples/WorkflowCore.Sample12/Program.cs index 937265e4f..c3b6e211a 100644 --- a/src/samples/WorkflowCore.Sample12/Program.cs +++ b/src/samples/WorkflowCore.Sample12/Program.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using System; using WorkflowCore.Interface; diff --git a/src/samples/WorkflowCore.Sample12/Steps/DetermineSomething.cs b/src/samples/WorkflowCore.Sample12/Steps/DetermineSomething.cs index 44f99d41b..807162e4e 100644 --- a/src/samples/WorkflowCore.Sample12/Steps/DetermineSomething.cs +++ b/src/samples/WorkflowCore.Sample12/Steps/DetermineSomething.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample12/Steps/PrintMessage.cs b/src/samples/WorkflowCore.Sample12/Steps/PrintMessage.cs index c655831d2..3809d0226 100644 --- a/src/samples/WorkflowCore.Sample12/Steps/PrintMessage.cs +++ b/src/samples/WorkflowCore.Sample12/Steps/PrintMessage.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample12/Steps/SayGoodbye.cs b/src/samples/WorkflowCore.Sample12/Steps/SayGoodbye.cs index ba4c581a3..7c2be887c 100644 --- a/src/samples/WorkflowCore.Sample12/Steps/SayGoodbye.cs +++ b/src/samples/WorkflowCore.Sample12/Steps/SayGoodbye.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample12/Steps/SayHello.cs b/src/samples/WorkflowCore.Sample12/Steps/SayHello.cs index b232aa55b..5fe4b5c3e 100644 --- a/src/samples/WorkflowCore.Sample12/Steps/SayHello.cs +++ b/src/samples/WorkflowCore.Sample12/Steps/SayHello.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample13/ParallelWorkflow.cs b/src/samples/WorkflowCore.Sample13/ParallelWorkflow.cs index 8b4ea0d0a..83209bcc3 100644 --- a/src/samples/WorkflowCore.Sample13/ParallelWorkflow.cs +++ b/src/samples/WorkflowCore.Sample13/ParallelWorkflow.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; -using WorkflowCore.Models; namespace WorkflowCore.Sample13 { diff --git a/src/samples/WorkflowCore.Sample13/Program.cs b/src/samples/WorkflowCore.Sample13/Program.cs index 9f5a22e7a..6e0ba9d0a 100644 --- a/src/samples/WorkflowCore.Sample13/Program.cs +++ b/src/samples/WorkflowCore.Sample13/Program.cs @@ -1,11 +1,6 @@ using System; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using WorkflowCore.Interface; -using System.Threading; -using System.Threading.Tasks; -using System.Security.Cryptography; -using System.Collections.Generic; namespace WorkflowCore.Sample13 { diff --git a/src/samples/WorkflowCore.Sample13/Steps/PrintMessage.cs b/src/samples/WorkflowCore.Sample13/Steps/PrintMessage.cs index dbb59578f..0cd23dc03 100644 --- a/src/samples/WorkflowCore.Sample13/Steps/PrintMessage.cs +++ b/src/samples/WorkflowCore.Sample13/Steps/PrintMessage.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample13/Steps/SayGoodbye.cs b/src/samples/WorkflowCore.Sample13/Steps/SayGoodbye.cs index b7779d3b8..40b851e56 100644 --- a/src/samples/WorkflowCore.Sample13/Steps/SayGoodbye.cs +++ b/src/samples/WorkflowCore.Sample13/Steps/SayGoodbye.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample13/Steps/SayHello.cs b/src/samples/WorkflowCore.Sample13/Steps/SayHello.cs index bf174e0c0..591025768 100644 --- a/src/samples/WorkflowCore.Sample13/Steps/SayHello.cs +++ b/src/samples/WorkflowCore.Sample13/Steps/SayHello.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample14/Program.cs b/src/samples/WorkflowCore.Sample14/Program.cs index b2ecabb2d..f12ae2621 100644 --- a/src/samples/WorkflowCore.Sample14/Program.cs +++ b/src/samples/WorkflowCore.Sample14/Program.cs @@ -1,6 +1,5 @@ using System; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using WorkflowCore.Interface; namespace WorkflowCore.Sample14 diff --git a/src/samples/WorkflowCore.Sample14/RecurSampleWorkflow.cs b/src/samples/WorkflowCore.Sample14/RecurSampleWorkflow.cs index d3d91f05b..862624479 100644 --- a/src/samples/WorkflowCore.Sample14/RecurSampleWorkflow.cs +++ b/src/samples/WorkflowCore.Sample14/RecurSampleWorkflow.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; -using WorkflowCore.Models; namespace WorkflowCore.Sample14 { diff --git a/src/samples/WorkflowCore.Sample15/HelloWorldWorkflow.cs b/src/samples/WorkflowCore.Sample15/HelloWorldWorkflow.cs index 7c2ed4984..4b1744add 100644 --- a/src/samples/WorkflowCore.Sample15/HelloWorldWorkflow.cs +++ b/src/samples/WorkflowCore.Sample15/HelloWorldWorkflow.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; -using WorkflowCore.Models; using WorkflowCore.Sample15.Steps; namespace WorkflowCore.Sample15 diff --git a/src/samples/WorkflowCore.Sample15/Program.cs b/src/samples/WorkflowCore.Sample15/Program.cs index 04d4c2a58..76d539baf 100644 --- a/src/samples/WorkflowCore.Sample15/Program.cs +++ b/src/samples/WorkflowCore.Sample15/Program.cs @@ -1,6 +1,5 @@ using System; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using WorkflowCore.Interface; using WorkflowCore.Sample15.Steps; using WorkflowCore.Sample15.Services; diff --git a/src/samples/WorkflowCore.Sample15/Services/MyService.cs b/src/samples/WorkflowCore.Sample15/Services/MyService.cs index 290805efd..8b8b322cf 100644 --- a/src/samples/WorkflowCore.Sample15/Services/MyService.cs +++ b/src/samples/WorkflowCore.Sample15/Services/MyService.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.Sample15.Services { diff --git a/src/samples/WorkflowCore.Sample15/Steps/DoSomething.cs b/src/samples/WorkflowCore.Sample15/Steps/DoSomething.cs index 5aeafdb3e..e8f7bff3b 100644 --- a/src/samples/WorkflowCore.Sample15/Steps/DoSomething.cs +++ b/src/samples/WorkflowCore.Sample15/Steps/DoSomething.cs @@ -1,8 +1,5 @@ -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; +using System; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Sample15.Services; diff --git a/src/samples/WorkflowCore.Sample15/Steps/HelloWorld.cs b/src/samples/WorkflowCore.Sample15/Steps/HelloWorld.cs index 6d32d532d..21dec311b 100644 --- a/src/samples/WorkflowCore.Sample15/Steps/HelloWorld.cs +++ b/src/samples/WorkflowCore.Sample15/Steps/HelloWorld.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample16/Program.cs b/src/samples/WorkflowCore.Sample16/Program.cs index 6ca03139d..db085a6d9 100644 --- a/src/samples/WorkflowCore.Sample16/Program.cs +++ b/src/samples/WorkflowCore.Sample16/Program.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using System; using WorkflowCore.Interface; diff --git a/src/samples/WorkflowCore.Sample16/ScheduleWorkflow.cs b/src/samples/WorkflowCore.Sample16/ScheduleWorkflow.cs index 47d4e72bd..69878f1b8 100644 --- a/src/samples/WorkflowCore.Sample16/ScheduleWorkflow.cs +++ b/src/samples/WorkflowCore.Sample16/ScheduleWorkflow.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; namespace WorkflowCore.Sample16 diff --git a/src/samples/WorkflowCore.Sample17/CompensatingWorkflow.cs b/src/samples/WorkflowCore.Sample17/CompensatingWorkflow.cs index 94db0806e..00a0ead8d 100644 --- a/src/samples/WorkflowCore.Sample17/CompensatingWorkflow.cs +++ b/src/samples/WorkflowCore.Sample17/CompensatingWorkflow.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; using WorkflowCore.Interface; using WorkflowCore.Sample17.Steps; diff --git a/src/samples/WorkflowCore.Sample18/ActivityWorkflow.cs b/src/samples/WorkflowCore.Sample18/ActivityWorkflow.cs index 126e2be15..22b32a782 100644 --- a/src/samples/WorkflowCore.Sample18/ActivityWorkflow.cs +++ b/src/samples/WorkflowCore.Sample18/ActivityWorkflow.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; using WorkflowCore.Interface; using WorkflowCore.Sample18.Steps; diff --git a/src/samples/WorkflowCore.Sample18/Program.cs b/src/samples/WorkflowCore.Sample18/Program.cs index 295701499..aa7d3f2f7 100644 --- a/src/samples/WorkflowCore.Sample18/Program.cs +++ b/src/samples/WorkflowCore.Sample18/Program.cs @@ -1,7 +1,5 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Console; -using Microsoft.Extensions.Logging.Debug; using System; using WorkflowCore.Interface; diff --git a/src/samples/WorkflowCore.Sample18/Steps/CustomMessage.cs b/src/samples/WorkflowCore.Sample18/Steps/CustomMessage.cs index 0d9803de3..69f1dd42c 100644 --- a/src/samples/WorkflowCore.Sample18/Steps/CustomMessage.cs +++ b/src/samples/WorkflowCore.Sample18/Steps/CustomMessage.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample18/Steps/GoodbyeWorld.cs b/src/samples/WorkflowCore.Sample18/Steps/GoodbyeWorld.cs index dffce0d6b..b42f3e913 100644 --- a/src/samples/WorkflowCore.Sample18/Steps/GoodbyeWorld.cs +++ b/src/samples/WorkflowCore.Sample18/Steps/GoodbyeWorld.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample18/Steps/HelloWorld.cs b/src/samples/WorkflowCore.Sample18/Steps/HelloWorld.cs index 8440b8cbe..8378bb7cd 100644 --- a/src/samples/WorkflowCore.Sample18/Steps/HelloWorld.cs +++ b/src/samples/WorkflowCore.Sample18/Steps/HelloWorld.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.Sample19/Program.cs b/src/samples/WorkflowCore.Sample19/Program.cs index 1d6e38a48..6d3074744 100644 --- a/src/samples/WorkflowCore.Sample19/Program.cs +++ b/src/samples/WorkflowCore.Sample19/Program.cs @@ -1,7 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; -using Microsoft.Extensions.Logging.Console; using WorkflowCore.Interface; using WorkflowCore.Sample19.Middleware; using WorkflowCore.Sample19.Steps; diff --git a/src/samples/WorkflowCore.TestSample01/NUnitTest.cs b/src/samples/WorkflowCore.TestSample01/NUnitTest.cs index d01aaf5cb..2b2b898e6 100644 --- a/src/samples/WorkflowCore.TestSample01/NUnitTest.cs +++ b/src/samples/WorkflowCore.TestSample01/NUnitTest.cs @@ -1,8 +1,6 @@ using FluentAssertions; using NUnit.Framework; using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Models; using WorkflowCore.Testing; using WorkflowCore.TestSample01.Workflow; diff --git a/src/samples/WorkflowCore.TestSample01/Workflow/AddNumbers.cs b/src/samples/WorkflowCore.TestSample01/Workflow/AddNumbers.cs index a45f06f9d..0ec30e24b 100644 --- a/src/samples/WorkflowCore.TestSample01/Workflow/AddNumbers.cs +++ b/src/samples/WorkflowCore.TestSample01/Workflow/AddNumbers.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/src/samples/WorkflowCore.TestSample01/Workflow/MyDataClass.cs b/src/samples/WorkflowCore.TestSample01/Workflow/MyDataClass.cs index 1db1d9273..84f1abf54 100644 --- a/src/samples/WorkflowCore.TestSample01/Workflow/MyDataClass.cs +++ b/src/samples/WorkflowCore.TestSample01/Workflow/MyDataClass.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.TestSample01.Workflow { diff --git a/src/samples/WorkflowCore.TestSample01/Workflow/MyWorkflow.cs b/src/samples/WorkflowCore.TestSample01/Workflow/MyWorkflow.cs index bf485e559..67b390873 100644 --- a/src/samples/WorkflowCore.TestSample01/Workflow/MyWorkflow.cs +++ b/src/samples/WorkflowCore.TestSample01/Workflow/MyWorkflow.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; namespace WorkflowCore.TestSample01.Workflow diff --git a/test/Docker.Testify/DockerSetup.cs b/test/Docker.Testify/DockerSetup.cs index 1f6b48b07..71bb76e26 100644 --- a/test/Docker.Testify/DockerSetup.cs +++ b/test/Docker.Testify/DockerSetup.cs @@ -3,12 +3,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; using System.Linq; using System.Net.NetworkInformation; using System.Runtime.InteropServices; -using System.Text; -using System.Threading; using System.Threading.Tasks; namespace Docker.Testify diff --git a/test/Docker.Testify/PortsInUseException.cs b/test/Docker.Testify/PortsInUseException.cs index 48a897c22..f4ad7ae07 100644 --- a/test/Docker.Testify/PortsInUseException.cs +++ b/test/Docker.Testify/PortsInUseException.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace Docker.Testify { diff --git a/test/ScratchPad/ElasticTest.cs b/test/ScratchPad/ElasticTest.cs index 6d8ae43f0..6401bda70 100644 --- a/test/ScratchPad/ElasticTest.cs +++ b/test/ScratchPad/ElasticTest.cs @@ -1,16 +1,7 @@ -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; +using System; using System.Linq; -using System.Threading; -using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.Interface; -using WorkflowCore.Models; -using System.Text; -using Amazon; -using Amazon.DynamoDBv2; -using Amazon.Runtime; using Nest; using WorkflowCore.Models.Search; diff --git a/test/ScratchPad/Program.cs b/test/ScratchPad/Program.cs index 3c0ee5f76..0d44810b9 100644 --- a/test/ScratchPad/Program.cs +++ b/test/ScratchPad/Program.cs @@ -1,5 +1,4 @@ -using Microsoft.Extensions.Logging; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -7,8 +6,6 @@ using Microsoft.Extensions.DependencyInjection; using WorkflowCore.Interface; using WorkflowCore.Models; -using System.Text; -using WorkflowCore.Services.DefinitionStorage; namespace ScratchPad { diff --git a/test/WorkflowCore.IntegrationTests/Properties/AssemblyInfo.cs b/test/WorkflowCore.IntegrationTests/Properties/AssemblyInfo.cs index 2a6d71492..f0355ab5a 100644 --- a/test/WorkflowCore.IntegrationTests/Properties/AssemblyInfo.cs +++ b/test/WorkflowCore.IntegrationTests/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs index ae7b372ab..1e082f4db 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/AttachScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/AttachScenario.cs index 9f7f93245..1c1fe7bdd 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/AttachScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/AttachScenario.cs @@ -1,11 +1,8 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; using FluentAssertions; -using System.Threading; using WorkflowCore.Testing; namespace WorkflowCore.IntegrationTests.Scenarios diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/BaseScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/BaseScenario.cs index 4e70b446c..db8211b44 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/BaseScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/BaseScenario.cs @@ -1,8 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; namespace WorkflowCore.IntegrationTests.Scenarios diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/BasicScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/BasicScenario.cs index 77b660088..5d5e0d37b 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/BasicScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/BasicScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/CancelledEventScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/CancelledEventScenario.cs index b0675f3f2..61b7a6540 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/CancelledEventScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/CancelledEventScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario.cs index a07d1e44a..2a6cc8da4 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario2.cs b/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario2.cs index d27564f07..bbb997d14 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario2.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/CompensationScenario2.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs index d5adab795..d8a12724d 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/DiScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/DiScenario.cs index 81a782264..fd100fe2d 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/DiScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/DiScenario.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.DependencyInjection; using Autofac.Extensions.DependencyInjection; using Autofac; -using System.Diagnostics; namespace WorkflowCore.IntegrationTests.Scenarios { diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/EndStepScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/EndStepScenario.cs index f950d58b3..f177423a8 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/EndStepScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/EndStepScenario.cs @@ -1,7 +1,5 @@ using FluentAssertions; using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Testing; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/EventOrderScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/EventOrderScenario.cs index 5ac5766ed..79fd2633d 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/EventOrderScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/EventOrderScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/EventScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/EventScenario.cs index 7d5fd2dea..6c5439b18 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/EventScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/EventScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/FailingSagaScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/FailingSagaScenario.cs index 36c12c3bd..b2f83ef65 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/FailingSagaScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/FailingSagaScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ForeachScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ForeachScenario.cs index f16c89b24..fb0747d5e 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/ForeachScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ForeachScenario.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ForkScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ForkScenario.cs index 54fb31432..89a9b46e0 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/ForkScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ForkScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/IfScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/IfScenario.cs index bd2c9808a..8b716715f 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/IfScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/IfScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/MultistepCompensationScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/MultistepCompensationScenario.cs index afdbe588a..0f080504a 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/MultistepCompensationScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/MultistepCompensationScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/NestedRetrySagaScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/NestedRetrySagaScenario.cs index dd4d2d720..f8b3c1a08 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/NestedRetrySagaScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/NestedRetrySagaScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ParallelScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ParallelScenario.cs index 12decbf73..f63041858 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/ParallelScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ParallelScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/RetrySagaScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/RetrySagaScenario.cs index 70ce71510..c4ac48238 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/RetrySagaScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/RetrySagaScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/SagaScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/SagaScenario.cs index bfa935ef7..de3dc1105 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/SagaScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/SagaScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs index eb51107b8..cbd04a40a 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; -using System.Text; -using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; using FluentAssertions; -using WorkflowCore.Services.DefinitionStorage; using WorkflowCore.Testing; using WorkflowCore.TestAssets.DataTypes; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs index 26b1f687a..449a6c855 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; -using System.Text; -using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; using FluentAssertions; -using WorkflowCore.Services.DefinitionStorage; using WorkflowCore.Testing; using WorkflowCore.TestAssets.DataTypes; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/UserScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/UserScenario.cs index b99ca99a8..66d442018 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/UserScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/UserScenario.cs @@ -1,12 +1,8 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; using FluentAssertions; -using FluentAssertions.Collections; -using WorkflowCore.Users.Models; using System.Linq; using WorkflowCore.Testing; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/WhenScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/WhenScenario.cs index 7d7095e6c..b56d4c81d 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/WhenScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/WhenScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/WhileScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/WhileScenario.cs index 5ca2cd20a..f91209d44 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/WhileScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/WhileScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using Xunit; diff --git a/test/WorkflowCore.IntegrationTests/SearchIndexTests.cs b/test/WorkflowCore.IntegrationTests/SearchIndexTests.cs index 091dafe22..cc9847574 100644 --- a/test/WorkflowCore.IntegrationTests/SearchIndexTests.cs +++ b/test/WorkflowCore.IntegrationTests/SearchIndexTests.cs @@ -1,9 +1,6 @@ using System; using System.Collections.Generic; using FluentAssertions; -using FluentAssertions.Collections; -using FluentAssertions.Equivalency; -using FluentAssertions.Common; using Xunit; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/test/WorkflowCore.TestAssets/DataTypes/CounterBoard.cs b/test/WorkflowCore.TestAssets/DataTypes/CounterBoard.cs index 3ef48c525..eec59ecd6 100644 --- a/test/WorkflowCore.TestAssets/DataTypes/CounterBoard.cs +++ b/test/WorkflowCore.TestAssets/DataTypes/CounterBoard.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace WorkflowCore.TestAssets.DataTypes { diff --git a/test/WorkflowCore.TestAssets/LockProvider/DistributedLockProviderTests.cs b/test/WorkflowCore.TestAssets/LockProvider/DistributedLockProviderTests.cs index 677fb511c..7ea5218bb 100644 --- a/test/WorkflowCore.TestAssets/LockProvider/DistributedLockProviderTests.cs +++ b/test/WorkflowCore.TestAssets/LockProvider/DistributedLockProviderTests.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Threading; using System.Threading.Tasks; using WorkflowCore.Interface; diff --git a/test/WorkflowCore.TestAssets/Properties/AssemblyInfo.cs b/test/WorkflowCore.TestAssets/Properties/AssemblyInfo.cs index 31e55a72d..1fccce37d 100644 --- a/test/WorkflowCore.TestAssets/Properties/AssemblyInfo.cs +++ b/test/WorkflowCore.TestAssets/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/test/WorkflowCore.TestAssets/Steps/Counter.cs b/test/WorkflowCore.TestAssets/Steps/Counter.cs index af5b433f4..64d276199 100644 --- a/test/WorkflowCore.TestAssets/Steps/Counter.cs +++ b/test/WorkflowCore.TestAssets/Steps/Counter.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; diff --git a/test/WorkflowCore.TestAssets/Utils.cs b/test/WorkflowCore.TestAssets/Utils.cs index 48a479b47..723cca992 100644 --- a/test/WorkflowCore.TestAssets/Utils.cs +++ b/test/WorkflowCore.TestAssets/Utils.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using Newtonsoft.Json; using System.IO; diff --git a/test/WorkflowCore.Testing/JsonWorkflowTest.cs b/test/WorkflowCore.Testing/JsonWorkflowTest.cs index cfabc7877..4e8f4281b 100644 --- a/test/WorkflowCore.Testing/JsonWorkflowTest.cs +++ b/test/WorkflowCore.Testing/JsonWorkflowTest.cs @@ -1,8 +1,6 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/test/WorkflowCore.Testing/WorkflowTest.cs b/test/WorkflowCore.Testing/WorkflowTest.cs index 3f8a29ea3..84db06002 100644 --- a/test/WorkflowCore.Testing/WorkflowTest.cs +++ b/test/WorkflowCore.Testing/WorkflowTest.cs @@ -1,8 +1,6 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; diff --git a/test/WorkflowCore.Testing/YamlWorkflowTest.cs b/test/WorkflowCore.Testing/YamlWorkflowTest.cs index a9d180b98..11b8e9d93 100644 --- a/test/WorkflowCore.Testing/YamlWorkflowTest.cs +++ b/test/WorkflowCore.Testing/YamlWorkflowTest.cs @@ -1,8 +1,6 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/test/WorkflowCore.Tests.DynamoDB/DynamoDbDockerSetup.cs b/test/WorkflowCore.Tests.DynamoDB/DynamoDbDockerSetup.cs index 6e52c238e..b9458fd1e 100644 --- a/test/WorkflowCore.Tests.DynamoDB/DynamoDbDockerSetup.cs +++ b/test/WorkflowCore.Tests.DynamoDB/DynamoDbDockerSetup.cs @@ -1,10 +1,5 @@ -using Docker.DotNet; -using Docker.DotNet.Models; -using System; -using System.Collections.Generic; +using System; using System.Net; -using System.Runtime.InteropServices; -using System.Text; using Docker.Testify; using Xunit; using Amazon.DynamoDBv2; diff --git a/test/WorkflowCore.Tests.DynamoDB/DynamoPersistenceProviderFixture.cs b/test/WorkflowCore.Tests.DynamoDB/DynamoPersistenceProviderFixture.cs index aa0663936..6fb9c1ea9 100644 --- a/test/WorkflowCore.Tests.DynamoDB/DynamoPersistenceProviderFixture.cs +++ b/test/WorkflowCore.Tests.DynamoDB/DynamoPersistenceProviderFixture.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Amazon.DynamoDBv2; using Microsoft.Extensions.Logging; using WorkflowCore.Interface; diff --git a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoBasicScenario.cs b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoBasicScenario.cs index 66a621c4f..8b6754c02 100644 --- a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoBasicScenario.cs +++ b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoBasicScenario.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; -using System.Text; using Amazon.DynamoDBv2; -using Amazon.Runtime; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.DynamoDB; using Xunit; namespace WorkflowCore.Tests.DynamoDB.Scenarios diff --git a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoCompensationScenario.cs b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoCompensationScenario.cs index 23ea7b32c..f475c58cb 100644 --- a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoCompensationScenario.cs +++ b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoCompensationScenario.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; -using System.Text; using Amazon.DynamoDBv2; -using Amazon.Runtime; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.DynamoDB; using Xunit; namespace WorkflowCore.Tests.DynamoDB.Scenarios diff --git a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoDataScenario.cs b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoDataScenario.cs index e0214203d..648b18868 100644 --- a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoDataScenario.cs +++ b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoDataScenario.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; -using System.Text; using Amazon.DynamoDBv2; -using Amazon.Runtime; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.DynamoDB; using Xunit; namespace WorkflowCore.Tests.DynamoDB.Scenarios diff --git a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoDynamicDataScenario.cs b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoDynamicDataScenario.cs index d5d0ff5ac..419d7ac37 100644 --- a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoDynamicDataScenario.cs +++ b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoDynamicDataScenario.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; -using System.Text; using Amazon.DynamoDBv2; -using Amazon.Runtime; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.DynamoDB; using Xunit; namespace WorkflowCore.Tests.DynamoDB.Scenarios diff --git a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoEventScenario.cs b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoEventScenario.cs index 887e39541..e421d31a2 100644 --- a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoEventScenario.cs +++ b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoEventScenario.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; -using System.Text; using Amazon.DynamoDBv2; -using Amazon.Runtime; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.DynamoDB; using Xunit; namespace WorkflowCore.Tests.DynamoDB.Scenarios diff --git a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoForeachScenario.cs b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoForeachScenario.cs index a8026da4b..1c9e30679 100644 --- a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoForeachScenario.cs +++ b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoForeachScenario.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; -using System.Text; using Amazon.DynamoDBv2; -using Amazon.Runtime; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.DynamoDB; using Xunit; namespace WorkflowCore.Tests.DynamoDB.Scenarios diff --git a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoIfScenario.cs b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoIfScenario.cs index 2b7ff3fac..efc3738d8 100644 --- a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoIfScenario.cs +++ b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoIfScenario.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; -using System.Text; using Amazon.DynamoDBv2; -using Amazon.Runtime; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.DynamoDB; using Xunit; namespace WorkflowCore.Tests.DynamoDB.Scenarios diff --git a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoRetrySagaScenario.cs b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoRetrySagaScenario.cs index a09dad420..5aea6ee1a 100644 --- a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoRetrySagaScenario.cs +++ b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoRetrySagaScenario.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; -using System.Text; using Amazon.DynamoDBv2; -using Amazon.Runtime; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.DynamoDB; using Xunit; namespace WorkflowCore.Tests.DynamoDB.Scenarios diff --git a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoSagaScenario.cs b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoSagaScenario.cs index 9cb309614..8c1f6a317 100644 --- a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoSagaScenario.cs +++ b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoSagaScenario.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; -using System.Text; using Amazon.DynamoDBv2; -using Amazon.Runtime; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.DynamoDB; using Xunit; namespace WorkflowCore.Tests.DynamoDB.Scenarios diff --git a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoWhileScenario.cs b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoWhileScenario.cs index 50960652a..7912b3f53 100644 --- a/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoWhileScenario.cs +++ b/test/WorkflowCore.Tests.DynamoDB/Scenarios/DynamoWhileScenario.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; -using System.Text; using Amazon.DynamoDBv2; -using Amazon.Runtime; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.DynamoDB; using Xunit; namespace WorkflowCore.Tests.DynamoDB.Scenarios diff --git a/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs b/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs index aef37beaa..4bb1c57f9 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs +++ b/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Net; -using System.Text; using Docker.Testify; using Nest; using Xunit; diff --git a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs index 515f3ed8a..9ce3ce7d7 100644 --- a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs +++ b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs @@ -1,9 +1,4 @@ -using Docker.DotNet; -using Docker.DotNet.Models; -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; +using System; using Docker.Testify; using MongoDB.Driver; using Xunit; diff --git a/test/WorkflowCore.Tests.MongoDB/MongoPersistenceProviderFixture.cs b/test/WorkflowCore.Tests.MongoDB/MongoPersistenceProviderFixture.cs index b3146105d..79de07a97 100644 --- a/test/WorkflowCore.Tests.MongoDB/MongoPersistenceProviderFixture.cs +++ b/test/WorkflowCore.Tests.MongoDB/MongoPersistenceProviderFixture.cs @@ -1,7 +1,5 @@ using MongoDB.Driver; using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Persistence.MongoDB.Services; using WorkflowCore.UnitTests; diff --git a/test/WorkflowCore.Tests.MongoDB/Properties/AssemblyInfo.cs b/test/WorkflowCore.Tests.MongoDB/Properties/AssemblyInfo.cs index 608b546e7..d533a178e 100644 --- a/test/WorkflowCore.Tests.MongoDB/Properties/AssemblyInfo.cs +++ b/test/WorkflowCore.Tests.MongoDB/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoActivityScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoActivityScenario.cs index 29682a442..52625678f 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoActivityScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoActivityScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using MongoDB.Bson.Serialization; using WorkflowCore.IntegrationTests.Scenarios; diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoBasicScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoBasicScenario.cs index 7ffad9531..bec7c6d50 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoBasicScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoBasicScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoCompensationScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoCompensationScenario.cs index 00fbec0c9..8adf4b4bd 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoCompensationScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoCompensationScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDataScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDataScenario.cs index 520c62f5d..468915f75 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDataScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDataScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDecisionScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDecisionScenario.cs index 828dda1a2..b5f8fd01f 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDecisionScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDecisionScenario.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; -using MongoDB.Bson.Serialization; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoEventScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoEventScenario.cs index af2e51006..b789bab5b 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoEventScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoEventScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForEachScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForEachScenario.cs index 756e76595..c8b718753 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForEachScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForEachScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForkScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForkScenario.cs index 40c2ef556..319af0466 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForkScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForkScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoIfScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoIfScenario.cs index 51e7beee3..7ea42fd98 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoIfScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoIfScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoRetrySagaScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoRetrySagaScenario.cs index 311043260..b8a9ec92b 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoRetrySagaScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoRetrySagaScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoSagaScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoSagaScenario.cs index 1e5e384f9..e5d666a9c 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoSagaScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoSagaScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoUserScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoUserScenario.cs index c082624b8..93ec848ee 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoUserScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoUserScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhenScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhenScenario.cs index 8c8925e52..6cca92b6b 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhenScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhenScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhileScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhileScenario.cs index 7f2bdc43b..4c7aaead9 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhileScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhileScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlDynamicDataScenario.cs b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlDynamicDataScenario.cs index 2b8dd3c9d..5ec59395d 100644 --- a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlDynamicDataScenario.cs +++ b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlDynamicDataScenario.cs @@ -1,7 +1,6 @@ using System; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.MySQL; using Xunit; namespace WorkflowCore.Tests.MySQL.Scenarios diff --git a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlEventScenario.cs b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlEventScenario.cs index 09838d64a..65e99ad84 100644 --- a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlEventScenario.cs +++ b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlEventScenario.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.MySQL; using Xunit; namespace WorkflowCore.Tests.MySQL.Scenarios diff --git a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlForeachScenario.cs b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlForeachScenario.cs index 23111adbd..01a15de17 100644 --- a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlForeachScenario.cs +++ b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlForeachScenario.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.MySQL; using Xunit; namespace WorkflowCore.Tests.MySQL.Scenarios diff --git a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlForkScenario.cs b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlForkScenario.cs index 0d2d43421..8a57e465b 100644 --- a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlForkScenario.cs +++ b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlForkScenario.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.MySQL; using Xunit; namespace WorkflowCore.Tests.MySQL.Scenarios diff --git a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlIfScenario.cs b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlIfScenario.cs index d02f5dbe7..7cf6721fc 100644 --- a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlIfScenario.cs +++ b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlIfScenario.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.MySQL; using Xunit; namespace WorkflowCore.Tests.MySQL.Scenarios diff --git a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlRetrySagaScenario.cs b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlRetrySagaScenario.cs index 12dcbeb58..f16190f73 100644 --- a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlRetrySagaScenario.cs +++ b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlRetrySagaScenario.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.MySQL; using Xunit; namespace WorkflowCore.Tests.MySQL.Scenarios diff --git a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlSagaScenario.cs b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlSagaScenario.cs index 2d88ea835..e23719b22 100644 --- a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlSagaScenario.cs +++ b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlSagaScenario.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.MySQL; using Xunit; namespace WorkflowCore.Tests.MySQL.Scenarios diff --git a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlUserScenario.cs b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlUserScenario.cs index 22017da65..909b98b4f 100644 --- a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlUserScenario.cs +++ b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlUserScenario.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.MySQL; using Xunit; namespace WorkflowCore.Tests.MySQL.Scenarios diff --git a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlWhenScenario.cs b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlWhenScenario.cs index dae355db2..e7721e382 100644 --- a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlWhenScenario.cs +++ b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlWhenScenario.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.MySQL; using Xunit; namespace WorkflowCore.Tests.MySQL.Scenarios diff --git a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlWhileScenario.cs b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlWhileScenario.cs index e6b07202e..8e6c5f6ee 100644 --- a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlWhileScenario.cs +++ b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlWhileScenario.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; -using WorkflowCore.Tests.MySQL; using Xunit; namespace WorkflowCore.Tests.MySQL.Scenarios diff --git a/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs b/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs index c5e1d93b1..253493803 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs @@ -1,10 +1,5 @@ -using Docker.DotNet; -using Docker.DotNet.Models; -using System; +using System; using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading; using Docker.Testify; using Npgsql; using Xunit; diff --git a/test/WorkflowCore.Tests.PostgreSQL/PostgresPersistenceProviderFixture.cs b/test/WorkflowCore.Tests.PostgreSQL/PostgresPersistenceProviderFixture.cs index 95ebe7976..9322b033a 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/PostgresPersistenceProviderFixture.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/PostgresPersistenceProviderFixture.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Persistence.EntityFramework.Services; using WorkflowCore.Persistence.PostgreSQL; diff --git a/test/WorkflowCore.Tests.PostgreSQL/Properties/AssemblyInfo.cs b/test/WorkflowCore.Tests.PostgreSQL/Properties/AssemblyInfo.cs index 1d2a140ee..9d931e022 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/Properties/AssemblyInfo.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresActivityScenario.cs b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresActivityScenario.cs index 7b63b42dd..2f31eca31 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresActivityScenario.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresActivityScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresBasicScenario.cs b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresBasicScenario.cs index 7b7817e20..2b1a8e62d 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresBasicScenario.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresBasicScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresDataScenario.cs b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresDataScenario.cs index e72fdcf07..3c0742b0b 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresDataScenario.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresDataScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresEventScenario.cs b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresEventScenario.cs index 3af74377b..ec9d520cb 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresEventScenario.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresEventScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresForeachScenario.cs b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresForeachScenario.cs index 49b2bd92b..a0c5e03f4 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresForeachScenario.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresForeachScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresForkScenario.cs b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresForkScenario.cs index 9719ab4b9..4ad8fe86a 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresForkScenario.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresForkScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresIfScenario.cs b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresIfScenario.cs index 68be367db..f962dd70d 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresIfScenario.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresIfScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresRetrySagaScenario.cs b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresRetrySagaScenario.cs index f8c792aa6..0c63d54ff 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresRetrySagaScenario.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresRetrySagaScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresSagaScenario.cs b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresSagaScenario.cs index 38f304029..2d42dcd10 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresSagaScenario.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresSagaScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresUserScenario.cs b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresUserScenario.cs index 57c8fc5b9..5c371bb93 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresUserScenario.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresUserScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresWhenScenario.cs b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresWhenScenario.cs index 9ffc43761..52445096a 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresWhenScenario.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresWhenScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresWhileScenario.cs b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresWhileScenario.cs index 91532221a..9aaa2583c 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresWhileScenario.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresWhileScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.Redis/RedisDockerSetup.cs b/test/WorkflowCore.Tests.Redis/RedisDockerSetup.cs index cfd3d11f2..91fd3e32a 100644 --- a/test/WorkflowCore.Tests.Redis/RedisDockerSetup.cs +++ b/test/WorkflowCore.Tests.Redis/RedisDockerSetup.cs @@ -1,8 +1,4 @@ -using Docker.DotNet; -using Docker.DotNet.Models; -using System; -using System.Collections.Generic; -using System.Net; +using System; using Docker.Testify; using StackExchange.Redis; using Xunit; diff --git a/test/WorkflowCore.Tests.Redis/RedisPersistenceProviderFixture.cs b/test/WorkflowCore.Tests.Redis/RedisPersistenceProviderFixture.cs index cb68f7753..22a898e2b 100644 --- a/test/WorkflowCore.Tests.Redis/RedisPersistenceProviderFixture.cs +++ b/test/WorkflowCore.Tests.Redis/RedisPersistenceProviderFixture.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.Logging; using WorkflowCore.Interface; using WorkflowCore.Providers.Redis.Services; diff --git a/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs b/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs index 6b589666d..74aff9487 100644 --- a/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs +++ b/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs @@ -1,11 +1,6 @@ -using Docker.DotNet; -using Docker.DotNet.Models; -using System; +using System; using System.Collections.Generic; using System.Data.SqlClient; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading; using Docker.Testify; using Xunit; diff --git a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerActivityScenario.cs b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerActivityScenario.cs index cf09f78e3..2094cdf66 100644 --- a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerActivityScenario.cs +++ b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerActivityScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerBasicScenario.cs b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerBasicScenario.cs index 1333131eb..56c951884 100644 --- a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerBasicScenario.cs +++ b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerBasicScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerCompenstationScenario.cs b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerCompenstationScenario.cs index 2114b5d19..63b8ff470 100644 --- a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerCompenstationScenario.cs +++ b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerCompenstationScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerDataScenario.cs b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerDataScenario.cs index e892534c4..0ecabc61f 100644 --- a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerDataScenario.cs +++ b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerDataScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerEventScenario.cs b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerEventScenario.cs index 32cb07dc2..fce8a9bae 100644 --- a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerEventScenario.cs +++ b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerEventScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerForEachScenario.cs b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerForEachScenario.cs index 2163fa998..b4df418d2 100644 --- a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerForEachScenario.cs +++ b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerForEachScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerIfScenario.cs b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerIfScenario.cs index e51c4a514..798863285 100644 --- a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerIfScenario.cs +++ b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerIfScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerRetrySagaScenario.cs b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerRetrySagaScenario.cs index 258ca298f..fd00b2d20 100644 --- a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerRetrySagaScenario.cs +++ b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerRetrySagaScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerSagaScenario.cs b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerSagaScenario.cs index 2f1bf58ae..b8e13f0c4 100644 --- a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerSagaScenario.cs +++ b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerSagaScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerWhenScenario.cs b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerWhenScenario.cs index 5180db8e9..77da4ee10 100644 --- a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerWhenScenario.cs +++ b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerWhenScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerWhileScenario.cs b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerWhileScenario.cs index cd870f805..832579484 100644 --- a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerWhileScenario.cs +++ b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerWhileScenario.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; diff --git a/test/WorkflowCore.Tests.Sqlite/SqliteCollection.cs b/test/WorkflowCore.Tests.Sqlite/SqliteCollection.cs index a57bc2c1b..69ed8c41a 100644 --- a/test/WorkflowCore.Tests.Sqlite/SqliteCollection.cs +++ b/test/WorkflowCore.Tests.Sqlite/SqliteCollection.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Xunit; namespace WorkflowCore.Tests.Sqlite diff --git a/test/WorkflowCore.Tests.Sqlite/SqlitePersistenceProviderFixture.cs b/test/WorkflowCore.Tests.Sqlite/SqlitePersistenceProviderFixture.cs index 5a27fd530..f8318ad9b 100644 --- a/test/WorkflowCore.Tests.Sqlite/SqlitePersistenceProviderFixture.cs +++ b/test/WorkflowCore.Tests.Sqlite/SqlitePersistenceProviderFixture.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Persistence.EntityFramework.Services; using WorkflowCore.Persistence.Sqlite; diff --git a/test/WorkflowCore.UnitTests/Models/MemberMapParameterTests.cs b/test/WorkflowCore.UnitTests/Models/MemberMapParameterTests.cs index b486d039e..81e667139 100644 --- a/test/WorkflowCore.UnitTests/Models/MemberMapParameterTests.cs +++ b/test/WorkflowCore.UnitTests/Models/MemberMapParameterTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq.Expressions; using System.Threading.Tasks; using WorkflowCore.Interface; diff --git a/test/WorkflowCore.UnitTests/Properties/AssemblyInfo.cs b/test/WorkflowCore.UnitTests/Properties/AssemblyInfo.cs index a44538b0e..4e6557e23 100644 --- a/test/WorkflowCore.UnitTests/Properties/AssemblyInfo.cs +++ b/test/WorkflowCore.UnitTests/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs index 0a9293523..6176b6ee6 100644 --- a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs +++ b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs @@ -1,15 +1,11 @@ using FakeItEasy; using FluentAssertions; using System; -using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Services.DefinitionStorage; using WorkflowCore.TestAssets.DataTypes; -using WorkflowCore.TestAssets.Steps; using Xunit; namespace WorkflowCore.UnitTests.Services.DefinitionStorage diff --git a/test/WorkflowCore.UnitTests/Services/ExecutionResultProcessorFixture.cs b/test/WorkflowCore.UnitTests/Services/ExecutionResultProcessorFixture.cs index f6bc0cf35..a5697882b 100644 --- a/test/WorkflowCore.UnitTests/Services/ExecutionResultProcessorFixture.cs +++ b/test/WorkflowCore.UnitTests/Services/ExecutionResultProcessorFixture.cs @@ -3,15 +3,12 @@ using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Services; using FluentAssertions; using Xunit; -using WorkflowCore.Primitives; using System.Linq.Expressions; -using System.Threading.Tasks; namespace WorkflowCore.UnitTests.Services { diff --git a/test/WorkflowCore.UnitTests/Services/MemoryPersistenceProviderFixture.cs b/test/WorkflowCore.UnitTests/Services/MemoryPersistenceProviderFixture.cs index f340f3010..1bfa2b3f7 100644 --- a/test/WorkflowCore.UnitTests/Services/MemoryPersistenceProviderFixture.cs +++ b/test/WorkflowCore.UnitTests/Services/MemoryPersistenceProviderFixture.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Services; diff --git a/test/WorkflowCore.UnitTests/Services/WorkflowRegistryFixture.cs b/test/WorkflowCore.UnitTests/Services/WorkflowRegistryFixture.cs index c3dbb96fd..3fb0bb75d 100644 --- a/test/WorkflowCore.UnitTests/Services/WorkflowRegistryFixture.cs +++ b/test/WorkflowCore.UnitTests/Services/WorkflowRegistryFixture.cs @@ -1,17 +1,9 @@ using FakeItEasy; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using System; -using System.Collections.Generic; -using System.Text; -using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Services; using FluentAssertions; using Xunit; -using WorkflowCore.Primitives; -using System.Linq.Expressions; -using System.Threading.Tasks; namespace WorkflowCore.UnitTests.Services { diff --git a/test/WorkflowCore.UnitTests/SingleNodeLockProviderTests/SingleNodeLockProviderTests.cs b/test/WorkflowCore.UnitTests/SingleNodeLockProviderTests/SingleNodeLockProviderTests.cs index d2cf041a5..f4f411ffb 100644 --- a/test/WorkflowCore.UnitTests/SingleNodeLockProviderTests/SingleNodeLockProviderTests.cs +++ b/test/WorkflowCore.UnitTests/SingleNodeLockProviderTests/SingleNodeLockProviderTests.cs @@ -1,8 +1,5 @@ -using FluentAssertions; -using NUnit.Framework; +using NUnit.Framework; using System; -using System.Collections.Generic; -using System.Text; using WorkflowCore.Interface; using WorkflowCore.Services; using WorkflowCore.TestAssets.LockProvider; From 106283b64987df3842fe1198083c9f6dedab3eab Mon Sep 17 00:00:00 2001 From: "divotchenko.gg" Date: Fri, 26 Mar 2021 09:55:06 +0300 Subject: [PATCH 102/342] Set CompleteTime to WorkflowInstance when terminating workflow. --- src/WorkflowCore/Models/WorkflowInstance.cs | 11 +++++------ .../Services/ErrorHandlers/TerminateHandler.cs | 14 ++++++++------ src/WorkflowCore/Services/WorkflowController.cs | 15 +++++++++------ src/WorkflowCore/Services/WorkflowExecutor.cs | 17 +++++++++-------- 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/WorkflowCore/Models/WorkflowInstance.cs b/src/WorkflowCore/Models/WorkflowInstance.cs index b75b284fc..71f1e3c28 100644 --- a/src/WorkflowCore/Models/WorkflowInstance.cs +++ b/src/WorkflowCore/Models/WorkflowInstance.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; namespace WorkflowCore.Models @@ -36,11 +35,11 @@ public bool IsBranchComplete(string parentId) } } - public enum WorkflowStatus + public enum WorkflowStatus { - Runnable = 0, - Suspended = 1, - Complete = 2, - Terminated = 3 + Runnable = 0, + Suspended = 1, + Complete = 2, + Terminated = 3, } } diff --git a/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs index d89f7f470..b8862d0e0 100755 --- a/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using System.Text; + using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Models.LifeCycleEvents; @@ -10,21 +10,23 @@ namespace WorkflowCore.Services.ErrorHandlers public class TerminateHandler : IWorkflowErrorHandler { private readonly ILifeCycleEventPublisher _eventPublisher; - private readonly IDateTimeProvider _datetimeProvider; + private readonly IDateTimeProvider _dateTimeProvider; public WorkflowErrorHandling Type => WorkflowErrorHandling.Terminate; - public TerminateHandler(ILifeCycleEventPublisher eventPublisher, IDateTimeProvider datetimeProvider) + public TerminateHandler(ILifeCycleEventPublisher eventPublisher, IDateTimeProvider dateTimeProvider) { _eventPublisher = eventPublisher; - _datetimeProvider = datetimeProvider; + _dateTimeProvider = dateTimeProvider; } public void Handle(WorkflowInstance workflow, WorkflowDefinition def, ExecutionPointer pointer, WorkflowStep step, Exception exception, Queue bubbleUpQueue) { workflow.Status = WorkflowStatus.Terminated; - _eventPublisher.PublishNotification(new WorkflowTerminated() + workflow.CompleteTime = _dateTimeProvider.UtcNow; + + _eventPublisher.PublishNotification(new WorkflowTerminated { - EventTimeUtc = _datetimeProvider.UtcNow, + EventTimeUtc = _dateTimeProvider.UtcNow, Reference = workflow.Reference, WorkflowInstanceId = workflow.Id, WorkflowDefinitionId = workflow.WorkflowDefinitionId, diff --git a/src/WorkflowCore/Services/WorkflowController.cs b/src/WorkflowCore/Services/WorkflowController.cs index 690a6a596..025346a10 100755 --- a/src/WorkflowCore/Services/WorkflowController.cs +++ b/src/WorkflowCore/Services/WorkflowController.cs @@ -1,8 +1,8 @@ using System; using System.Linq; -using System.Reflection; using System.Threading; using System.Threading.Tasks; + using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using WorkflowCore.Exceptions; @@ -47,10 +47,10 @@ public Task StartWorkflow(string workflowId, int? version, object data = return StartWorkflow(workflowId, version, data, reference); } - public Task StartWorkflow(string workflowId, TData data = null, string reference=null) + public Task StartWorkflow(string workflowId, TData data = null, string reference = null) where TData : class, new() { - return StartWorkflow(workflowId, null, data, reference); + return StartWorkflow(workflowId, null, data, reference); } public async Task StartWorkflow(string workflowId, int? version, TData data = null, string reference=null) @@ -204,7 +204,10 @@ public async Task TerminateWorkflow(string workflowId) try { var wf = await _persistenceStore.GetWorkflowInstance(workflowId); + wf.Status = WorkflowStatus.Terminated; + wf.CompleteTime = _dateTimeProvider.UtcNow; + await _persistenceStore.PersistWorkflow(wf); await _queueProvider.QueueWork(workflowId, QueueType.Index); await _eventHub.PublishNotification(new WorkflowTerminated() @@ -226,7 +229,7 @@ await _eventHub.PublishNotification(new WorkflowTerminated() public void RegisterWorkflow() where TWorkflow : IWorkflow { - TWorkflow wf = ActivatorUtilities.CreateInstance(_serviceProvider); + var wf = ActivatorUtilities.CreateInstance(_serviceProvider); _registry.RegisterWorkflow(wf); } @@ -234,8 +237,8 @@ public void RegisterWorkflow() where TWorkflow : IWorkflow where TData : new() { - TWorkflow wf = ActivatorUtilities.CreateInstance(_serviceProvider); - _registry.RegisterWorkflow(wf); + var wf = ActivatorUtilities.CreateInstance(_serviceProvider); + _registry.RegisterWorkflow(wf); } } } diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index c6241fd64..30d3d91a9 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -1,9 +1,10 @@ -using Microsoft.Extensions.Logging; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; + +using Microsoft.Extensions.Logging; using Microsoft.Extensions.DependencyInjection; using WorkflowCore.Interface; using WorkflowCore.Models; @@ -62,7 +63,7 @@ public async Task Execute(WorkflowInstance workflow, Can { _logger.LogError("Unable to find step {0} in workflow definition", pointer.StepId); pointer.SleepUntil = _datetimeProvider.UtcNow.Add(_options.ErrorRetryInterval); - wfResult.Errors.Add(new ExecutionError() + wfResult.Errors.Add(new ExecutionError { WorkflowId = workflow.Id, ExecutionPointerId = pointer.Id, @@ -82,7 +83,7 @@ public async Task Execute(WorkflowInstance workflow, Can catch (Exception ex) { _logger.LogError(ex, "Workflow {0} raised error on step {1} Message: {2}", workflow.Id, pointer.StepId, ex.Message); - wfResult.Errors.Add(new ExecutionError() + wfResult.Errors.Add(new ExecutionError { WorkflowId = workflow.Id, ExecutionPointerId = pointer.Id, @@ -116,7 +117,7 @@ private bool InitializeStep(WorkflowInstance workflow, WorkflowStep step, Workfl if (pointer.Status != PointerStatus.Running) { pointer.Status = PointerStatus.Running; - _publisher.PublishNotification(new StepStarted() + _publisher.PublishNotification(new StepStarted { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, @@ -159,12 +160,12 @@ private async Task ExecuteStep(WorkflowInstance workflow, WorkflowStep step, Exe { _logger.LogError("Unable to construct step body {0}", step.BodyType.ToString()); pointer.SleepUntil = _datetimeProvider.UtcNow.Add(_options.ErrorRetryInterval); - wfResult.Errors.Add(new ExecutionError() + wfResult.Errors.Add(new ExecutionError { WorkflowId = workflow.Id, ExecutionPointerId = pointer.Id, ErrorTime = _datetimeProvider.UtcNow, - Message = $"Unable to construct step body {step.BodyType.ToString()}" + Message = $"Unable to construct step body {step.BodyType}" }); return; } @@ -253,7 +254,7 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo await middlewareRunner.RunPostMiddleware(workflow, def); } - _publisher.PublishNotification(new WorkflowCompleted() + _publisher.PublishNotification(new WorkflowCompleted { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, From e54fec2e4cf5cbee2f41f4ba9fd761ff13c9ab9a Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 2 Apr 2021 11:05:47 -0700 Subject: [PATCH 103/342] fix registry --- src/WorkflowCore/Services/WorkflowRegistry.cs | 67 +++++++++++-------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/src/WorkflowCore/Services/WorkflowRegistry.cs b/src/WorkflowCore/Services/WorkflowRegistry.cs index 01d0625a5..beed19c0e 100644 --- a/src/WorkflowCore/Services/WorkflowRegistry.cs +++ b/src/WorkflowCore/Services/WorkflowRegistry.cs @@ -10,8 +10,9 @@ namespace WorkflowCore.Services { public class WorkflowRegistry : IWorkflowRegistry { - private readonly IServiceProvider _serviceProvider; - private readonly BlockingCollection<(string workflowId, int version, WorkflowDefinition definition)> _registry = new BlockingCollection<(string, int, WorkflowDefinition)>(); + private readonly IServiceProvider _serviceProvider; + private readonly ConcurrentDictionary _registry = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _lastestVersion = new ConcurrentDictionary(); public WorkflowRegistry(IServiceProvider serviceProvider) { @@ -20,75 +21,85 @@ public WorkflowRegistry(IServiceProvider serviceProvider) public WorkflowDefinition GetDefinition(string workflowId, int? version = null) { - (string workflowId, int version, WorkflowDefinition definition) workflowEntry; if (version.HasValue) { - workflowEntry = _registry.FirstOrDefault(x => x.workflowId == workflowId && x.version == version.Value); + if (!_registry.ContainsKey($"{workflowId}-{version}")) + return default; + return _registry[$"{workflowId}-{version}"]; } else { - workflowEntry = _registry.Where(x => x.workflowId == workflowId).OrderByDescending(x => x.version) - .FirstOrDefault(); + if (!_lastestVersion.ContainsKey(workflowId)) + return default; + return _lastestVersion[workflowId]; } - - return workflowEntry != default ? workflowEntry.definition : default; } public void DeregisterWorkflow(string workflowId, int version) { - var definition = _registry.FirstOrDefault(x => x.workflowId == workflowId && x.version == version); - if (definition != default) + if (!_registry.ContainsKey($"{workflowId}-{version}")) + return; + + lock (_registry) { - _registry.TryTake(out definition); + _registry.TryRemove($"{workflowId}-{version}", out var _); + if (_lastestVersion[workflowId].Version == version) + { + _lastestVersion.TryRemove(workflowId, out var _); + + var latest = _registry.Values.Where(x => x.Id == workflowId).OrderByDescending(x => x.Version).FirstOrDefault(); + if (latest != default) + _lastestVersion[workflowId] = latest; + } } } public void RegisterWorkflow(IWorkflow workflow) { - if (_registry.Any(x => x.workflowId == workflow.Id && x.version == workflow.Version)) - { - throw new InvalidOperationException($"Workflow {workflow.Id} version {workflow.Version} is already registered"); - } - var builder = _serviceProvider.GetService().UseData(); workflow.Build(builder); var def = builder.Build(workflow.Id, workflow.Version); - _registry.Add((workflow.Id, workflow.Version, def)); + RegisterWorkflow(def); } public void RegisterWorkflow(WorkflowDefinition definition) { - if (_registry.Any(x => x.workflowId == definition.Id && x.version == definition.Version)) + if (_registry.ContainsKey($"{definition.Id}-{definition.Version}")) { throw new InvalidOperationException($"Workflow {definition.Id} version {definition.Version} is already registered"); } - _registry.Add((definition.Id, definition.Version, definition)); + lock (_registry) + { + _registry[$"{definition.Id}-{definition.Version}"] = definition; + if (!_lastestVersion.ContainsKey(definition.Id)) + { + _lastestVersion[definition.Id] = definition; + return; + } + + if (_lastestVersion[definition.Id].Version <= definition.Version) + _lastestVersion[definition.Id] = definition; + } } public void RegisterWorkflow(IWorkflow workflow) where TData : new() { - if (_registry.Any(x => x.workflowId == workflow.Id && x.version == workflow.Version)) - { - throw new InvalidOperationException($"Workflow {workflow.Id} version {workflow.Version} is already registered"); - } - var builder = _serviceProvider.GetService().UseData(); workflow.Build(builder); var def = builder.Build(workflow.Id, workflow.Version); - _registry.Add((workflow.Id, workflow.Version, def)); + RegisterWorkflow(def); } public bool IsRegistered(string workflowId, int version) { - var definition = _registry.FirstOrDefault(x => x.workflowId == workflowId && x.version == version); - return definition != default; + return _registry.ContainsKey($"{workflowId}-{version}"); } public IEnumerable GetAllDefinitions() { - return _registry.Select(i => i.definition); + return _registry.Values; } } } \ No newline at end of file From 97ba822fda48d4f2ed59cac155f35e33c12d2b91 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 2 Apr 2021 11:12:45 -0700 Subject: [PATCH 104/342] fix test constructor --- src/samples/WorkflowCore.TestSample01/NUnitTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/samples/WorkflowCore.TestSample01/NUnitTest.cs b/src/samples/WorkflowCore.TestSample01/NUnitTest.cs index 2b2b898e6..91be04202 100644 --- a/src/samples/WorkflowCore.TestSample01/NUnitTest.cs +++ b/src/samples/WorkflowCore.TestSample01/NUnitTest.cs @@ -11,9 +11,9 @@ namespace WorkflowCore.TestSample01 public class NUnitTest : WorkflowTest { [SetUp] - protected override void Setup(bool registerClassMap = false) + protected void Setup() { - base.Setup(registerClassMap); + base.Setup(false); } [Test] From 0c9085c504d2b2907fa08de5866bcc988f23d8ef Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 2 Apr 2021 11:13:26 -0700 Subject: [PATCH 105/342] bump version --- src/WorkflowCore/WorkflowCore.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 2f465db0d..2ef5a4a1c 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.3.5 - 3.3.5.0 - 3.3.5.0 + 3.3.6 + 3.3.6.0 + 3.3.6.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.3.5 + 3.3.6 From 00f790d77237445182e8fab11c612f1acf319439 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Mon, 5 Apr 2021 08:44:24 -0700 Subject: [PATCH 106/342] pr templates --- .github/PULL_REQUEST_TEMPLATE/bug_fix.md | 33 ++++++++++++++++++++ .github/PULL_REQUEST_TEMPLATE/new_feature.md | 23 ++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE/bug_fix.md create mode 100644 .github/PULL_REQUEST_TEMPLATE/new_feature.md diff --git a/.github/PULL_REQUEST_TEMPLATE/bug_fix.md b/.github/PULL_REQUEST_TEMPLATE/bug_fix.md new file mode 100644 index 000000000..0147a0895 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/bug_fix.md @@ -0,0 +1,33 @@ +--- +name: Bug Fix +about: Fixing an issue with existing functionality. +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Describe the change** +A clear and concise description of what the change is. + +**Describe your implementation or design** +How did you go about implementating the change? + +**Tests** +Did you cover your changes with tests? + +**Breaking change** +Do you changes break compatibility with previous versions? + + +**Additonal context** +Any additonal information you'd like to provide? diff --git a/.github/PULL_REQUEST_TEMPLATE/new_feature.md b/.github/PULL_REQUEST_TEMPLATE/new_feature.md new file mode 100644 index 000000000..cee9ea093 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/new_feature.md @@ -0,0 +1,23 @@ +--- +name: New Fuctionality +about: Adding new functionality to enable more use cases +title: '' +labels: '' +assignees: '' + +--- + +**Describe the change** +A clear and concise description of what the change is. + +**Describe your implementation or design** +How did you go about implementating the change? + +**Tests** +Did you cover your changes with tests? + +**Breaking change** +Do you changes break compatibility with previous versions? + +**Additonal context** +Any additonal information you'd like to provide? \ No newline at end of file From 1cd2168cfe3870a6185461712ce852e3a11370a7 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Mon, 5 Apr 2021 08:52:58 -0700 Subject: [PATCH 107/342] pr template --- .github/PULL_REQUEST_TEMPLATE/bug_fix.md | 33 ------------------- ...ew_feature.md => pull_request_template.md} | 10 +----- 2 files changed, 1 insertion(+), 42 deletions(-) delete mode 100644 .github/PULL_REQUEST_TEMPLATE/bug_fix.md rename .github/{PULL_REQUEST_TEMPLATE/new_feature.md => pull_request_template.md} (63%) diff --git a/.github/PULL_REQUEST_TEMPLATE/bug_fix.md b/.github/PULL_REQUEST_TEMPLATE/bug_fix.md deleted file mode 100644 index 0147a0895..000000000 --- a/.github/PULL_REQUEST_TEMPLATE/bug_fix.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -name: Bug Fix -about: Fixing an issue with existing functionality. -title: '' -labels: '' -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Describe the change** -A clear and concise description of what the change is. - -**Describe your implementation or design** -How did you go about implementating the change? - -**Tests** -Did you cover your changes with tests? - -**Breaking change** -Do you changes break compatibility with previous versions? - - -**Additonal context** -Any additonal information you'd like to provide? diff --git a/.github/PULL_REQUEST_TEMPLATE/new_feature.md b/.github/pull_request_template.md similarity index 63% rename from .github/PULL_REQUEST_TEMPLATE/new_feature.md rename to .github/pull_request_template.md index cee9ea093..9c41f2455 100644 --- a/.github/PULL_REQUEST_TEMPLATE/new_feature.md +++ b/.github/pull_request_template.md @@ -1,14 +1,6 @@ ---- -name: New Fuctionality -about: Adding new functionality to enable more use cases -title: '' -labels: '' -assignees: '' - ---- **Describe the change** -A clear and concise description of what the change is. +A clear and concise description of what the change is. Any PR submitted without a description of the change will not be reviewed. **Describe your implementation or design** How did you go about implementating the change? From 30c98f83c5d70bae11dd2b65bada0db5619340f3 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Mon, 5 Apr 2021 08:54:19 -0700 Subject: [PATCH 108/342] spelling --- .github/pull_request_template.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 9c41f2455..30d77c8db 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -3,7 +3,7 @@ A clear and concise description of what the change is. Any PR submitted without a description of the change will not be reviewed. **Describe your implementation or design** -How did you go about implementating the change? +How did you go about implementing the change? **Tests** Did you cover your changes with tests? @@ -11,5 +11,5 @@ Did you cover your changes with tests? **Breaking change** Do you changes break compatibility with previous versions? -**Additonal context** -Any additonal information you'd like to provide? \ No newline at end of file +**Additional context** +Any additional information you'd like to provide? \ No newline at end of file From 5a44e400447b34dd1ace141e5b7d06595dd628e3 Mon Sep 17 00:00:00 2001 From: Bruce Zlata Date: Thu, 15 Apr 2021 15:41:41 +0800 Subject: [PATCH 109/342] fix cosmos client leak # Add CosmosDbClient which implements a interface for DI # Use singleton for CosmosDbClient and it will be disposed by dotnet container # Fix EnsureStoreExists deaklock risk --- .../Interface/ICosmosDbClient.cs | 9 ++++ .../ServiceCollectionExtensions.cs | 5 +- .../Services/CosmosDbClient.cs | 48 +++++++++++++++++++ .../Services/CosmosDbPersistenceProvider.cs | 14 +++--- .../Services/CosmosDbProvisioner.cs | 8 ++-- 5 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbClient.cs create mode 100644 src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbClient.cs diff --git a/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbClient.cs b/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbClient.cs new file mode 100644 index 000000000..bf5c2275c --- /dev/null +++ b/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbClient.cs @@ -0,0 +1,9 @@ +using Microsoft.Azure.Cosmos; + +namespace WorkflowCore.Providers.Azure.Interface +{ + public interface ICosmosDbClient + { + CosmosClient GetCosmosClient(); + } +} \ No newline at end of file diff --git a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs index 9129e4de5..bdfd29d1e 100644 --- a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs @@ -28,8 +28,9 @@ public static WorkflowOptions UseAzureServiceBusEventHub( public static WorkflowOptions UseCosmosDbPersistence(this WorkflowOptions options, string connectionString, string databaseId) { - options.Services.AddTransient(sp => new CosmosDbProvisioner(connectionString, sp.GetService())); - options.UsePersistence(sp => new CosmosDbPersistenceProvider(connectionString, databaseId, sp.GetService())); + options.Services.AddSingleton(sp => new CosmosDbClient(connectionString)); + options.Services.AddTransient(sp => new CosmosDbProvisioner(sp.GetService(), sp.GetService())); + options.UsePersistence(sp => new CosmosDbPersistenceProvider(sp.GetService(), databaseId, sp.GetService())); return options; } } diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbClient.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbClient.cs new file mode 100644 index 000000000..cda487e14 --- /dev/null +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbClient.cs @@ -0,0 +1,48 @@ +using System; +using Microsoft.Azure.Cosmos; +using WorkflowCore.Providers.Azure.Interface; + +namespace WorkflowCore.Providers.Azure.Services +{ + public class CosmosDbClient : ICosmosDbClient, IDisposable + { + private bool isDisposed = false; + + public CosmosClient _client; + + public CosmosDbClient(string connectionString) + { + _client = new CosmosClient(connectionString); + } + + public CosmosClient GetCosmosClient() + { + return this._client; + } + + /// + /// Dispose of cosmos client + /// + public void Dispose() + { + this.Dispose(true); + } + + /// + /// Dispose of cosmos client + /// + /// True if disposing + protected virtual void Dispose(bool disposing) + { + if (!this.isDisposed) + { + if (disposing) + { + this._client.Dispose(); + } + + this.isDisposed = true; + } + } + } +} \ No newline at end of file diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs index a30ca8f27..e3fbc97f0 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs @@ -19,19 +19,19 @@ public class CosmosDbPersistenceProvider : IPersistenceProvider private ICosmosDbProvisioner _provisioner; private string _dbId; - private CosmosClient _client; + private ICosmosDbClient _client; private Lazy _workflowContainer; private Lazy _eventContainer; private Lazy _subscriptionContainer; - public CosmosDbPersistenceProvider(string connectionString, string dbId, ICosmosDbProvisioner provisioner) + public CosmosDbPersistenceProvider(ICosmosDbClient client, string dbId, ICosmosDbProvisioner provisioner) { _provisioner = provisioner; _dbId = dbId; - _client = new CosmosClient(connectionString); - _workflowContainer = new Lazy(() => _client.GetDatabase(_dbId).GetContainer(WorkflowContainerName)); - _eventContainer = new Lazy(() => _client.GetDatabase(_dbId).GetContainer(EventContainerName)); - _subscriptionContainer = new Lazy(() => _client.GetDatabase(_dbId).GetContainer(SubscriptionContainerName)); + _client = client; + _workflowContainer = new Lazy(() => _client.GetCosmosClient().GetDatabase(_dbId).GetContainer(WorkflowContainerName)); + _eventContainer = new Lazy(() => _client.GetCosmosClient().GetDatabase(_dbId).GetContainer(EventContainerName)); + _subscriptionContainer = new Lazy(() => _client.GetCosmosClient().GetDatabase(_dbId).GetContainer(SubscriptionContainerName)); } public async Task ClearSubscriptionToken(string eventSubscriptionId, string token) @@ -70,7 +70,7 @@ public async Task CreateNewWorkflow(WorkflowInstance workflow) public void EnsureStoreExists() { - _provisioner.Provision(_dbId).Wait(); + _provisioner.Provision(_dbId).ConfigureAwait(false).GetAwaiter().GetResult(); } public async Task GetEvent(string id) diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs index ab86cc3f6..359ef799e 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs @@ -9,16 +9,16 @@ namespace WorkflowCore.Providers.Azure.Services public class CosmosDbProvisioner : ICosmosDbProvisioner { - private CosmosClient _client; + private ICosmosDbClient _client; - public CosmosDbProvisioner(string connectionString, ILoggerFactory loggerFactory) + public CosmosDbProvisioner(ICosmosDbClient client, ILoggerFactory loggerFactory) { - _client = new CosmosClient(connectionString); + _client = client; } public async Task Provision(string dbId) { - var dbResp = await _client.CreateDatabaseIfNotExistsAsync(dbId); + var dbResp = await _client.GetCosmosClient().CreateDatabaseIfNotExistsAsync(dbId); var wfIndexPolicy = new IndexingPolicy(); wfIndexPolicy.IncludedPaths.Add(new IncludedPath { Path = @"/*" }); wfIndexPolicy.ExcludedPaths.Add(new ExcludedPath { Path = @"/ExecutionPointers/?" }); From 98df2bbac23c0b69934c8666269e77adb88b9ea9 Mon Sep 17 00:00:00 2001 From: glucaci Date: Thu, 15 Apr 2021 23:41:57 +0300 Subject: [PATCH 110/342] Add new WorkflowMiddlewarePhase --- .../Interface/IWorkflowMiddleware.cs | 7 +++- .../Interface/IWorkflowMiddlewareRunner.cs | 13 ++++++- src/WorkflowCore/Services/WorkflowExecutor.cs | 12 +++++-- .../Services/WorkflowMiddlewareRunner.cs | 35 ++++++------------- 4 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/WorkflowCore/Interface/IWorkflowMiddleware.cs b/src/WorkflowCore/Interface/IWorkflowMiddleware.cs index 71781b30d..ede4ca8ec 100644 --- a/src/WorkflowCore/Interface/IWorkflowMiddleware.cs +++ b/src/WorkflowCore/Interface/IWorkflowMiddleware.cs @@ -16,7 +16,12 @@ public enum WorkflowMiddlewarePhase /// /// The middleware should run after a workflow completes. /// - PostWorkflow + PostWorkflow, + + /// + /// The middleware should run after each workflow execution. + /// + ExecuteWorkflow } /// diff --git a/src/WorkflowCore/Interface/IWorkflowMiddlewareRunner.cs b/src/WorkflowCore/Interface/IWorkflowMiddlewareRunner.cs index 96aab8b74..6c47899f5 100644 --- a/src/WorkflowCore/Interface/IWorkflowMiddlewareRunner.cs +++ b/src/WorkflowCore/Interface/IWorkflowMiddlewareRunner.cs @@ -4,7 +4,7 @@ namespace WorkflowCore.Interface { /// - /// Runs workflow pre/post middleware. + /// Runs workflow pre/post and execute middleware. /// public interface IWorkflowMiddlewareRunner { @@ -29,5 +29,16 @@ public interface IWorkflowMiddlewareRunner /// The definition. /// A task that will complete when all middleware has run. Task RunPostMiddleware(WorkflowInstance workflow, WorkflowDefinition def); + + /// + /// Runs workflow-level middleware that is set to run at the + /// phase. Middleware will be run in the + /// order in which they were registered with DI with middleware declared earlier starting earlier and + /// completing later. + /// + /// The to run for. + /// The definition. + /// A task that will complete when all middleware has run. + Task RunExecuteMiddleware(WorkflowInstance workflow, WorkflowDefinition def); } } diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index ee58e32bb..5c72355a4 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -96,12 +96,12 @@ public async Task Execute(WorkflowInstance workflow, Can _cancellationProcessor.ProcessCancellations(workflow, def, wfResult); } ProcessAfterExecutionIteration(workflow, def, wfResult); - DetermineNextExecutionTime(workflow, def); + await DetermineNextExecutionTime(workflow, def); using (var scope = _serviceProvider.CreateScope()) { var middlewareRunner = scope.ServiceProvider.GetRequiredService(); - await middlewareRunner.RunPostMiddleware(workflow, def); + await middlewareRunner.RunExecuteMiddleware(workflow, def); } return wfResult; @@ -212,7 +212,7 @@ private void ProcessAfterExecutionIteration(WorkflowInstance workflow, WorkflowD } } - private void DetermineNextExecutionTime(WorkflowInstance workflow, WorkflowDefinition def) + private async Task DetermineNextExecutionTime(WorkflowInstance workflow, WorkflowDefinition def) { //TODO: move to own class workflow.NextExecution = null; @@ -257,6 +257,12 @@ private void DetermineNextExecutionTime(WorkflowInstance workflow, WorkflowDefin workflow.Status = WorkflowStatus.Complete; workflow.CompleteTime = _datetimeProvider.UtcNow; + using (var scope = _serviceProvider.CreateScope()) + { + var middlewareRunner = scope.ServiceProvider.GetRequiredService(); + await middlewareRunner.RunPostMiddleware(workflow, def); + } + _publisher.PublishNotification(new WorkflowCompleted { EventTimeUtc = _datetimeProvider.UtcNow, diff --git a/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs b/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs index 6eb6968b8..9b6eea445 100644 --- a/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs +++ b/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs @@ -8,7 +8,7 @@ namespace WorkflowCore.Services { - /// + /// public class WorkflowMiddlewareRunner : IWorkflowMiddlewareRunner { private static readonly WorkflowDelegate NoopWorkflowDelegate = () => Task.CompletedTask; @@ -17,23 +17,13 @@ public class WorkflowMiddlewareRunner : IWorkflowMiddlewareRunner public WorkflowMiddlewareRunner( IEnumerable middleware, - IServiceProvider serviceProvider - ) + IServiceProvider serviceProvider) { _middleware = middleware; _serviceProvider = serviceProvider; } - - /// - /// Runs workflow-level middleware that is set to run at the - /// phase. Middleware will be run in the - /// order in which they were registered with DI with middleware declared earlier starting earlier and - /// completing later. - /// - /// The to run for. - /// The definition. - /// A task that will complete when all middleware has run. + /// public async Task RunPreMiddleware(WorkflowInstance workflow, WorkflowDefinition def) { var preMiddleware = _middleware @@ -43,15 +33,7 @@ public async Task RunPreMiddleware(WorkflowInstance workflow, WorkflowDefinition await RunWorkflowMiddleware(workflow, preMiddleware); } - /// - /// Runs workflow-level middleware that is set to run at the - /// phase. Middleware will be run in the - /// order in which they were registered with DI with middleware declared earlier starting earlier and - /// completing later. - /// - /// The to run for. - /// The definition. - /// A task that will complete when all middleware has run. + /// public async Task RunPostMiddleware(WorkflowInstance workflow, WorkflowDefinition def) { var postMiddleware = _middleware @@ -77,10 +59,15 @@ public async Task RunPostMiddleware(WorkflowInstance workflow, WorkflowDefinitio } } + /// + public Task RunExecuteMiddleware(WorkflowInstance workflow, WorkflowDefinition def) + { + throw new NotImplementedException(); + } + private static async Task RunWorkflowMiddleware( WorkflowInstance workflow, - IEnumerable middlewareCollection - ) + IEnumerable middlewareCollection) { // Build the middleware chain var middlewareChain = middlewareCollection From 076d1b8dfbe25f8421f6642f45b1da86ae5927ee Mon Sep 17 00:00:00 2001 From: glucaci Date: Fri, 16 Apr 2021 00:03:27 +0300 Subject: [PATCH 111/342] Add execute middleware implementation --- .../Services/WorkflowMiddlewareRunner.cs | 60 +++++++++++-------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs b/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs index 9b6eea445..d22470412 100644 --- a/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs +++ b/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs @@ -27,8 +27,7 @@ public WorkflowMiddlewareRunner( public async Task RunPreMiddleware(WorkflowInstance workflow, WorkflowDefinition def) { var preMiddleware = _middleware - .Where(m => m.Phase == WorkflowMiddlewarePhase.PreWorkflow) - .ToArray(); + .Where(m => m.Phase == WorkflowMiddlewarePhase.PreWorkflow); await RunWorkflowMiddleware(workflow, preMiddleware); } @@ -37,47 +36,58 @@ public async Task RunPreMiddleware(WorkflowInstance workflow, WorkflowDefinition public async Task RunPostMiddleware(WorkflowInstance workflow, WorkflowDefinition def) { var postMiddleware = _middleware - .Where(m => m.Phase == WorkflowMiddlewarePhase.PostWorkflow) - .ToArray(); - + .Where(m => m.Phase == WorkflowMiddlewarePhase.PostWorkflow); try { await RunWorkflowMiddleware(workflow, postMiddleware); } catch (Exception exception) { - // On error, determine which error handler to run and then run it + // TODO: + // OnPostMiddlewareError should be IWorkflowMiddlewareErrorHandler + // because we don't know to run other error handler type var errorHandlerType = def.OnPostMiddlewareError ?? typeof(IWorkflowMiddlewareErrorHandler); - using (var scope = _serviceProvider.CreateScope()) - { - var typeInstance = scope.ServiceProvider.GetService(errorHandlerType); - if (typeInstance != null && typeInstance is IWorkflowMiddlewareErrorHandler handler) - { - await handler.HandleAsync(exception); - } - } + await HandleWorkflowMiddlewareError(exception); } } /// - public Task RunExecuteMiddleware(WorkflowInstance workflow, WorkflowDefinition def) + public async Task RunExecuteMiddleware(WorkflowInstance workflow, WorkflowDefinition def) + { + var executeMiddleware = _middleware + .Where(m => m.Phase == WorkflowMiddlewarePhase.ExecuteWorkflow); + + try + { + await RunWorkflowMiddleware(workflow, executeMiddleware); + } + catch (Exception exception) + { + await HandleWorkflowMiddlewareError(exception); + } + } + + private async Task HandleWorkflowMiddlewareError(Exception exception) { - throw new NotImplementedException(); + using (var scope = _serviceProvider.CreateScope()) + { + var handler = scope.ServiceProvider.GetService(); + if (handler != null) + { + await handler.HandleAsync(exception); + } + } } - private static async Task RunWorkflowMiddleware( + private static Task RunWorkflowMiddleware( WorkflowInstance workflow, IEnumerable middlewareCollection) { - // Build the middleware chain - var middlewareChain = middlewareCollection + return middlewareCollection .Reverse() - .Aggregate( - NoopWorkflowDelegate, - (previous, middleware) => () => middleware.HandleAsync(workflow, previous) - ); - - await middlewareChain(); + .Aggregate(NoopWorkflowDelegate, + (previous, middleware) => + () => middleware.HandleAsync(workflow, previous))(); } } } From 2f28bd5b000230b4da0e5e22a09da24dbfe63556 Mon Sep 17 00:00:00 2001 From: glucaci Date: Fri, 16 Apr 2021 00:20:13 +0300 Subject: [PATCH 112/342] Add custom error handler for execute workflow middleware and tests --- src/WorkflowCore/Models/WorkflowDefinition.cs | 1 + .../Services/WorkflowMiddlewareRunner.cs | 34 +++--- .../Services/WorkflowMiddlewareRunnerTests.cs | 114 ++++++++++++++++++ 3 files changed, 131 insertions(+), 18 deletions(-) diff --git a/src/WorkflowCore/Models/WorkflowDefinition.cs b/src/WorkflowCore/Models/WorkflowDefinition.cs index 0cea6cc40..d40fc5a2e 100644 --- a/src/WorkflowCore/Models/WorkflowDefinition.cs +++ b/src/WorkflowCore/Models/WorkflowDefinition.cs @@ -18,6 +18,7 @@ public class WorkflowDefinition public WorkflowErrorHandling DefaultErrorBehavior { get; set; } public Type OnPostMiddlewareError { get; set; } + public Type OnExecuteMiddlewareError { get; set; } public TimeSpan? DefaultErrorRetryInterval { get; set; } diff --git a/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs b/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs index d22470412..872721849 100644 --- a/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs +++ b/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs @@ -43,11 +43,7 @@ public async Task RunPostMiddleware(WorkflowInstance workflow, WorkflowDefinitio } catch (Exception exception) { - // TODO: - // OnPostMiddlewareError should be IWorkflowMiddlewareErrorHandler - // because we don't know to run other error handler type - var errorHandlerType = def.OnPostMiddlewareError ?? typeof(IWorkflowMiddlewareErrorHandler); - await HandleWorkflowMiddlewareError(exception); + await HandleWorkflowMiddlewareError(def.OnPostMiddlewareError, exception); } } @@ -63,19 +59,7 @@ public async Task RunExecuteMiddleware(WorkflowInstance workflow, WorkflowDefini } catch (Exception exception) { - await HandleWorkflowMiddlewareError(exception); - } - } - - private async Task HandleWorkflowMiddlewareError(Exception exception) - { - using (var scope = _serviceProvider.CreateScope()) - { - var handler = scope.ServiceProvider.GetService(); - if (handler != null) - { - await handler.HandleAsync(exception); - } + await HandleWorkflowMiddlewareError(def.OnExecuteMiddlewareError, exception); } } @@ -89,5 +73,19 @@ private static Task RunWorkflowMiddleware( (previous, middleware) => () => middleware.HandleAsync(workflow, previous))(); } + + private async Task HandleWorkflowMiddlewareError(Type middlewareErrorType, Exception exception) + { + var errorHandlerType = middlewareErrorType ?? typeof(IWorkflowMiddlewareErrorHandler); + + using (var scope = _serviceProvider.CreateScope()) + { + var typeInstance = scope.ServiceProvider.GetService(errorHandlerType); + if (typeInstance is IWorkflowMiddlewareErrorHandler handler) + { + await handler.HandleAsync(exception); + } + } + } } } diff --git a/test/WorkflowCore.UnitTests/Services/WorkflowMiddlewareRunnerTests.cs b/test/WorkflowCore.UnitTests/Services/WorkflowMiddlewareRunnerTests.cs index 991acfb23..0e9c0da07 100644 --- a/test/WorkflowCore.UnitTests/Services/WorkflowMiddlewareRunnerTests.cs +++ b/test/WorkflowCore.UnitTests/Services/WorkflowMiddlewareRunnerTests.cs @@ -238,6 +238,120 @@ public async Task .MustHaveHappenedOnceExactly(); } + [Fact(DisplayName = "RunExecuteMiddleware should run nothing when no middleware")] + public void RunExecuteMiddleware_should_run_nothing_when_no_middleware() + { + // Act + Func action = async () => await Runner.RunExecuteMiddleware(Workflow, Definition); + + // Assert + action.ShouldNotThrow(); + } + + [Fact(DisplayName = "RunExecuteMiddleware should run middleware when one middleware")] + public async Task RunExecuteMiddleware_should_run_middleware_when_one_middleware() + { + // Arrange + var middleware = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.ExecuteWorkflow); + Middleware.Add(middleware); + + // Act + await Runner.RunExecuteMiddleware(Workflow, Definition); + + // Assert + A + .CallTo(HandleMethodFor(middleware)) + .MustHaveHappenedOnceExactly(); + } + + [Fact(DisplayName = "RunExecuteMiddleware should run all middleware when multiple middleware")] + public async Task RunExecuteMiddleware_should_run_all_middleware_when_multiple_middleware() + { + // Arrange + var middleware1 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.ExecuteWorkflow, 1); + var middleware2 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.ExecuteWorkflow, 2); + var middleware3 = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.ExecuteWorkflow, 3); + Middleware.AddRange(new[] { middleware1, middleware2, middleware3 }); + + // Act + await Runner.RunPostMiddleware(Workflow, Definition); + + // Assert + A + .CallTo(HandleMethodFor(middleware3)) + .MustHaveHappenedOnceExactly() + .Then(A + .CallTo(HandleMethodFor(middleware2)) + .MustHaveHappenedOnceExactly()) + .Then(A + .CallTo(HandleMethodFor(middleware1)) + .MustHaveHappenedOnceExactly()); + } + + [Fact(DisplayName = "RunExecuteMiddleware should run middleware in ExecuteWorkflow and PostWorkflow phase")] + public async Task RunExecuteMiddleware_should_run_middleware_in_ExecuteWorkflow_and_PostWorkflow_phase() + { + // Arrange + var executeMiddleware = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.ExecuteWorkflow, 1); + var postMiddleware = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PostWorkflow, 2); + var preMiddleware = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.PreWorkflow, 3); + Middleware.AddRange(new[] { preMiddleware, postMiddleware, executeMiddleware }); + + // Act + // TODO: add same test when workflow not completed + await Runner.RunExecuteMiddleware(Workflow, Definition); + + // Assert + A + .CallTo(HandleMethodFor(executeMiddleware)) + .MustHaveHappenedOnceExactly() + .Then(A + .CallTo(HandleMethodFor(postMiddleware)) + .MustHaveHappenedOnceExactly()); + + A.CallTo(HandleMethodFor(preMiddleware)).MustNotHaveHappened(); + } + + [Fact(DisplayName = "RunExecuteMiddleware should call top level error handler when middleware throws")] + public async Task RunExecuteMiddleware_should_call_top_level_error_handler_when_middleware_throws() + { + // Arrange + var middleware = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.ExecuteWorkflow, 1); + A.CallTo(HandleMethodFor(middleware)).ThrowsAsync(new ApplicationException("Something went wrong")); + Middleware.AddRange(new[] { middleware }); + + // Act + await Runner.RunExecuteMiddleware(Workflow, Definition); + + // Assert + A + .CallTo(HandleMethodFor(TopLevelErrorHandler)) + .MustHaveHappenedOnceExactly(); + } + + [Fact(DisplayName = + "RunExecuteMiddleware should call error handler on workflow def when middleware throws and def has handler defined")] + public async Task + RunExecuteMiddleware_should_call_error_handler_on_workflow_def_when_middleware_throws_and_def_has_handler() + { + // Arrange + var middleware = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.ExecuteWorkflow, 1); + A.CallTo(HandleMethodFor(middleware)).ThrowsAsync(new ApplicationException("Something went wrong")); + Middleware.AddRange(new[] { middleware }); + Definition.OnExecuteMiddlewareError = typeof(IDefLevelErrorHandler); + + // Act + await Runner.RunExecuteMiddleware(Workflow, Definition); + + // Assert + A + .CallTo(HandleMethodFor(TopLevelErrorHandler)) + .MustNotHaveHappened(); + A + .CallTo(HandleMethodFor(DefLevelErrorHandler)) + .MustHaveHappenedOnceExactly(); + } + #region Helpers private IWorkflowMiddleware BuildWorkflowMiddleware( From ae7d64f150e84f0755ecbc8cadaa842fcda78a6a Mon Sep 17 00:00:00 2001 From: glucaci Date: Fri, 16 Apr 2021 00:21:58 +0300 Subject: [PATCH 113/342] Add tests --- .../Services/WorkflowMiddlewareRunnerTests.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/test/WorkflowCore.UnitTests/Services/WorkflowMiddlewareRunnerTests.cs b/test/WorkflowCore.UnitTests/Services/WorkflowMiddlewareRunnerTests.cs index 0e9c0da07..4b58d965f 100644 --- a/test/WorkflowCore.UnitTests/Services/WorkflowMiddlewareRunnerTests.cs +++ b/test/WorkflowCore.UnitTests/Services/WorkflowMiddlewareRunnerTests.cs @@ -274,7 +274,7 @@ public async Task RunExecuteMiddleware_should_run_all_middleware_when_multiple_m Middleware.AddRange(new[] { middleware1, middleware2, middleware3 }); // Act - await Runner.RunPostMiddleware(Workflow, Definition); + await Runner.RunExecuteMiddleware(Workflow, Definition); // Assert A @@ -288,8 +288,8 @@ public async Task RunExecuteMiddleware_should_run_all_middleware_when_multiple_m .MustHaveHappenedOnceExactly()); } - [Fact(DisplayName = "RunExecuteMiddleware should run middleware in ExecuteWorkflow and PostWorkflow phase")] - public async Task RunExecuteMiddleware_should_run_middleware_in_ExecuteWorkflow_and_PostWorkflow_phase() + [Fact(DisplayName = "RunExecuteMiddleware should only run middleware in ExecuteWorkflow phase")] + public async Task RunExecuteMiddleware_should_only_run_middleware_in_ExecuteWorkflow_phase() { // Arrange var executeMiddleware = BuildWorkflowMiddleware(WorkflowMiddlewarePhase.ExecuteWorkflow, 1); @@ -298,18 +298,15 @@ public async Task RunExecuteMiddleware_should_run_middleware_in_ExecuteWorkflow_ Middleware.AddRange(new[] { preMiddleware, postMiddleware, executeMiddleware }); // Act - // TODO: add same test when workflow not completed await Runner.RunExecuteMiddleware(Workflow, Definition); // Assert A .CallTo(HandleMethodFor(executeMiddleware)) - .MustHaveHappenedOnceExactly() - .Then(A - .CallTo(HandleMethodFor(postMiddleware)) - .MustHaveHappenedOnceExactly()); + .MustHaveHappenedOnceExactly(); A.CallTo(HandleMethodFor(preMiddleware)).MustNotHaveHappened(); + A.CallTo(HandleMethodFor(postMiddleware)).MustNotHaveHappened(); } [Fact(DisplayName = "RunExecuteMiddleware should call top level error handler when middleware throws")] From 0239cd3a76cf0b71f13adb335a3c6f28ccf96b1b Mon Sep 17 00:00:00 2001 From: glucaci Date: Fri, 16 Apr 2021 00:40:35 +0300 Subject: [PATCH 114/342] Add two more tests --- .../Services/WorkflowExecutorFixture.cs | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs b/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs index 037dd0e33..e548b8e88 100644 --- a/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs +++ b/test/WorkflowCore.UnitTests/Services/WorkflowExecutorFixture.cs @@ -44,8 +44,14 @@ public WorkflowExecutorFixture() Options = new WorkflowOptions(A.Fake()); + var stepExecutionScope = A.Fake(); + A.CallTo(() => ScopeProvider.CreateScope(A._)).Returns(stepExecutionScope); + A.CallTo(() => stepExecutionScope.ServiceProvider).Returns(ServiceProvider); + var scope = A.Fake(); - A.CallTo(() => ScopeProvider.CreateScope(A._)).Returns(scope); + var scopeFactory = A.Fake(); + A.CallTo(() => ServiceProvider.GetService(typeof(IServiceScopeFactory))).Returns(scopeFactory); + A.CallTo(() => scopeFactory.CreateScope()).Returns(scope); A.CallTo(() => scope.ServiceProvider).Returns(ServiceProvider); A.CallTo(() => DateTimeProvider.Now).Returns(DateTime.Now); @@ -63,6 +69,10 @@ public WorkflowExecutorFixture() .RunPostMiddleware(A._, A._)) .Returns(Task.CompletedTask); + A.CallTo(() => MiddlewareRunner + .RunExecuteMiddleware(A._, A._)) + .Returns(Task.CompletedTask); + A.CallTo(() => StepExecutor.ExecuteStep(A._, A._)) .ReturnsLazily(call => call.Arguments[1].As().RunAsync( @@ -105,6 +115,64 @@ public void should_execute_active_step() A.CallTo(() => ResultProcesser.ProcessExecutionResult(instance, A.Ignored, A.Ignored, step1, A.Ignored, A.Ignored)).MustHaveHappened(); } + [Fact(DisplayName = "Should call execute middleware when not completed")] + public void should_call_execute_middleware_when_not_completed() + { + //arrange + var step1Body = A.Fake(); + A.CallTo(() => step1Body.RunAsync(A.Ignored)).Returns(ExecutionResult.Next()); + WorkflowStep step1 = BuildFakeStep(step1Body); + Given1StepWorkflow(step1, "Workflow", 1); + + var instance = new WorkflowInstance + { + WorkflowDefinitionId = "Workflow", + Version = 1, + Status = WorkflowStatus.Runnable, + NextExecution = 0, + Id = "001", + ExecutionPointers = new ExecutionPointerCollection(new List + { + new ExecutionPointer { Id = "1", Active = true, StepId = 0 } + }) + }; + + //act + Subject.Execute(instance); + + //assert + A.CallTo(() => MiddlewareRunner.RunExecuteMiddleware(instance, A.Ignored)).MustHaveHappened(); + } + + [Fact(DisplayName = "Should not call post middleware when not completed")] + public void should_not_call_post_middleware_when_not_completed() + { + //arrange + var step1Body = A.Fake(); + A.CallTo(() => step1Body.RunAsync(A.Ignored)).Returns(ExecutionResult.Next()); + WorkflowStep step1 = BuildFakeStep(step1Body); + Given1StepWorkflow(step1, "Workflow", 1); + + var instance = new WorkflowInstance + { + WorkflowDefinitionId = "Workflow", + Version = 1, + Status = WorkflowStatus.Runnable, + NextExecution = 0, + Id = "001", + ExecutionPointers = new ExecutionPointerCollection(new List + { + new ExecutionPointer { Id = "1", Active = true, StepId = 0 } + }) + }; + + //act + Subject.Execute(instance); + + //assert + A.CallTo(() => MiddlewareRunner.RunPostMiddleware(instance, A.Ignored)).MustNotHaveHappened(); + } + [Fact(DisplayName = "Should trigger step hooks")] public void should_trigger_step_hooks() { From 2164e0cb273c793fe4a7b05603f401e0707ef310 Mon Sep 17 00:00:00 2001 From: glucaci Date: Fri, 16 Apr 2021 00:47:22 +0300 Subject: [PATCH 115/342] Cleanup --- .../Services/WorkflowMiddlewareRunner.cs | 59 +++++++++---------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs b/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs index 872721849..d341ed1ec 100644 --- a/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs +++ b/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs @@ -33,33 +33,46 @@ public async Task RunPreMiddleware(WorkflowInstance workflow, WorkflowDefinition } /// - public async Task RunPostMiddleware(WorkflowInstance workflow, WorkflowDefinition def) + public Task RunPostMiddleware(WorkflowInstance workflow, WorkflowDefinition def) { - var postMiddleware = _middleware - .Where(m => m.Phase == WorkflowMiddlewarePhase.PostWorkflow); - try - { - await RunWorkflowMiddleware(workflow, postMiddleware); - } - catch (Exception exception) - { - await HandleWorkflowMiddlewareError(def.OnPostMiddlewareError, exception); - } + return RunWorkflowMiddlewareWithErrorHandling( + workflow, + WorkflowMiddlewarePhase.PostWorkflow, + def.OnPostMiddlewareError); } /// - public async Task RunExecuteMiddleware(WorkflowInstance workflow, WorkflowDefinition def) + public Task RunExecuteMiddleware(WorkflowInstance workflow, WorkflowDefinition def) { - var executeMiddleware = _middleware - .Where(m => m.Phase == WorkflowMiddlewarePhase.ExecuteWorkflow); + return RunWorkflowMiddlewareWithErrorHandling( + workflow, + WorkflowMiddlewarePhase.ExecuteWorkflow, + def.OnExecuteMiddlewareError); + } + + public async Task RunWorkflowMiddlewareWithErrorHandling( + WorkflowInstance workflow, + WorkflowMiddlewarePhase phase, + Type middlewareErrorType) + { + var middleware = _middleware.Where(m => m.Phase == phase); try { - await RunWorkflowMiddleware(workflow, executeMiddleware); + await RunWorkflowMiddleware(workflow, middleware); } catch (Exception exception) { - await HandleWorkflowMiddlewareError(def.OnExecuteMiddlewareError, exception); + var errorHandlerType = middlewareErrorType ?? typeof(IWorkflowMiddlewareErrorHandler); + + using (var scope = _serviceProvider.CreateScope()) + { + var typeInstance = scope.ServiceProvider.GetService(errorHandlerType); + if (typeInstance is IWorkflowMiddlewareErrorHandler handler) + { + await handler.HandleAsync(exception); + } + } } } @@ -73,19 +86,5 @@ private static Task RunWorkflowMiddleware( (previous, middleware) => () => middleware.HandleAsync(workflow, previous))(); } - - private async Task HandleWorkflowMiddlewareError(Type middlewareErrorType, Exception exception) - { - var errorHandlerType = middlewareErrorType ?? typeof(IWorkflowMiddlewareErrorHandler); - - using (var scope = _serviceProvider.CreateScope()) - { - var typeInstance = scope.ServiceProvider.GetService(errorHandlerType); - if (typeInstance is IWorkflowMiddlewareErrorHandler handler) - { - await handler.HandleAsync(exception); - } - } - } } } From 8fd8bba630e645b309e3c932c749f9762b25326d Mon Sep 17 00:00:00 2001 From: glucaci Date: Fri, 16 Apr 2021 00:48:31 +0300 Subject: [PATCH 116/342] Cleanup --- src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs b/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs index d341ed1ec..d904c5aa5 100644 --- a/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs +++ b/src/WorkflowCore/Services/WorkflowMiddlewareRunner.cs @@ -82,9 +82,9 @@ private static Task RunWorkflowMiddleware( { return middlewareCollection .Reverse() - .Aggregate(NoopWorkflowDelegate, - (previous, middleware) => - () => middleware.HandleAsync(workflow, previous))(); + .Aggregate( + NoopWorkflowDelegate, + (previous, middleware) => () => middleware.HandleAsync(workflow, previous))(); } } } From ead1dcba97dc9c081490449a15b352a387ebc580 Mon Sep 17 00:00:00 2001 From: Bruce Zlata Date: Fri, 16 Apr 2021 08:44:40 +0800 Subject: [PATCH 117/342] Change cosmosclient to private and add new line by end of file --- .../WorkflowCore.Providers.Azure/Interface/ICosmosDbClient.cs | 2 +- .../WorkflowCore.Providers.Azure/Services/CosmosDbClient.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbClient.cs b/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbClient.cs index bf5c2275c..fd9233164 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbClient.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbClient.cs @@ -6,4 +6,4 @@ public interface ICosmosDbClient { CosmosClient GetCosmosClient(); } -} \ No newline at end of file +} diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbClient.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbClient.cs index cda487e14..337e4de77 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbClient.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbClient.cs @@ -8,7 +8,7 @@ public class CosmosDbClient : ICosmosDbClient, IDisposable { private bool isDisposed = false; - public CosmosClient _client; + private CosmosClient _client; public CosmosDbClient(string connectionString) { @@ -45,4 +45,4 @@ protected virtual void Dispose(bool disposing) } } } -} \ No newline at end of file +} From 045cb49ecaf3a89ded5ee4184c16b70030573306 Mon Sep 17 00:00:00 2001 From: glucaci Date: Sun, 18 Apr 2021 23:19:59 +0300 Subject: [PATCH 118/342] Add release notes and increment minor --- ReleaseNotes/3.4.0.md | 55 ++++++++++++++++++++++++++++ src/WorkflowCore/WorkflowCore.csproj | 8 ++-- 2 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 ReleaseNotes/3.4.0.md diff --git a/ReleaseNotes/3.4.0.md b/ReleaseNotes/3.4.0.md new file mode 100644 index 000000000..ca724c4b2 --- /dev/null +++ b/ReleaseNotes/3.4.0.md @@ -0,0 +1,55 @@ +# Workflow Core 3.4.0 + +## Execute Workflow Middleware + +These middleware get run after each workflow execution and can be used to perform additional actions or build metrics/statistics for all workflows in your app. + +The following example illustrates how you can use a execute workflow middleware to build [prometheus](https://prometheus.io/) metrics. + +Note that you use `WorkflowMiddlewarePhase.ExecuteWorkflow` to specify that it runs after each workflow execution. + +**Important:** You should call `next` as part of the workflow middleware to ensure that the next workflow in the chain runs. + +```cs +public class MetricsMiddleware : IWorkflowMiddleware +{ + private readonly ConcurrentHashSet() _suspendedWorkflows = + new ConcurrentHashSet(); + + private readonly Counter _completed; + private readonly Counter _suspended; + + public MetricsMiddleware() + { + _completed = Prometheus.Metrics.CreateCounter( + "workflow_completed", "Workflow completed"); + + _suspended = Prometheus.Metrics.CreateCounter( + "workflow_suspended", "Workflow suspended"); + } + + public WorkflowMiddlewarePhase Phase => + WorkflowMiddlewarePhase.ExecuteWorkflow; + + public Task HandleAsync( + WorkflowInstance workflow, + WorkflowDelegate next) + { + switch (workflow.Status) + { + case WorkflowStatus.Complete: + if (_suspendedWorkflows.TryRemove(workflow.Id)) + { + _suspended.Dec(); + } + _completed.Inc(); + break; + case WorkflowStatus.Suspended: + _suspended.Inc(); + break; + } + + return next(); + } +} +``` \ No newline at end of file diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 2ef5a4a1c..a439d3bac 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -15,12 +15,12 @@ false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.3.6 - 3.3.6.0 - 3.3.6.0 + 3.4.0 + 3.4.0.0 + 3.4.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.3.6 + 3.4.0 From 3f1bf247d8e7e64e8ad0fb72ce8a4edc08abd621 Mon Sep 17 00:00:00 2001 From: Bruce Zlata Date: Mon, 19 Apr 2021 13:54:38 +0800 Subject: [PATCH 119/342] Naming to CosmosClientFactory --- .../{ICosmosDbClient.cs => ICosmosClientFactory.cs} | 2 +- .../ServiceCollectionExtensions.cs | 6 +++--- .../{CosmosDbClient.cs => CosmosClientFactory.cs} | 4 ++-- .../Services/CosmosDbPersistenceProvider.cs | 12 ++++++------ .../Services/CosmosDbProvisioner.cs | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) rename src/providers/WorkflowCore.Providers.Azure/Interface/{ICosmosDbClient.cs => ICosmosClientFactory.cs} (76%) rename src/providers/WorkflowCore.Providers.Azure/Services/{CosmosDbClient.cs => CosmosClientFactory.cs} (88%) diff --git a/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbClient.cs b/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosClientFactory.cs similarity index 76% rename from src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbClient.cs rename to src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosClientFactory.cs index fd9233164..cf8b44c47 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbClient.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosClientFactory.cs @@ -2,7 +2,7 @@ namespace WorkflowCore.Providers.Azure.Interface { - public interface ICosmosDbClient + public interface ICosmosClientFactory { CosmosClient GetCosmosClient(); } diff --git a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs index bdfd29d1e..96fff8f1d 100644 --- a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs @@ -28,9 +28,9 @@ public static WorkflowOptions UseAzureServiceBusEventHub( public static WorkflowOptions UseCosmosDbPersistence(this WorkflowOptions options, string connectionString, string databaseId) { - options.Services.AddSingleton(sp => new CosmosDbClient(connectionString)); - options.Services.AddTransient(sp => new CosmosDbProvisioner(sp.GetService(), sp.GetService())); - options.UsePersistence(sp => new CosmosDbPersistenceProvider(sp.GetService(), databaseId, sp.GetService())); + options.Services.AddSingleton(sp => new CosmosClientFactory(connectionString)); + options.Services.AddTransient(sp => new CosmosDbProvisioner(sp.GetService(), sp.GetService())); + options.UsePersistence(sp => new CosmosDbPersistenceProvider(sp.GetService(), databaseId, sp.GetService())); return options; } } diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbClient.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs similarity index 88% rename from src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbClient.cs rename to src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs index 337e4de77..9cb4cc572 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbClient.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs @@ -4,13 +4,13 @@ namespace WorkflowCore.Providers.Azure.Services { - public class CosmosDbClient : ICosmosDbClient, IDisposable + public class CosmosClientFactory : ICosmosClientFactory, IDisposable { private bool isDisposed = false; private CosmosClient _client; - public CosmosDbClient(string connectionString) + public CosmosClientFactory(string connectionString) { _client = new CosmosClient(connectionString); } diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs index e3fbc97f0..a666322aa 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs @@ -19,19 +19,19 @@ public class CosmosDbPersistenceProvider : IPersistenceProvider private ICosmosDbProvisioner _provisioner; private string _dbId; - private ICosmosDbClient _client; + private ICosmosClientFactory _clientFactory; private Lazy _workflowContainer; private Lazy _eventContainer; private Lazy _subscriptionContainer; - public CosmosDbPersistenceProvider(ICosmosDbClient client, string dbId, ICosmosDbProvisioner provisioner) + public CosmosDbPersistenceProvider(ICosmosClientFactory clientFactory, string dbId, ICosmosDbProvisioner provisioner) { _provisioner = provisioner; _dbId = dbId; - _client = client; - _workflowContainer = new Lazy(() => _client.GetCosmosClient().GetDatabase(_dbId).GetContainer(WorkflowContainerName)); - _eventContainer = new Lazy(() => _client.GetCosmosClient().GetDatabase(_dbId).GetContainer(EventContainerName)); - _subscriptionContainer = new Lazy(() => _client.GetCosmosClient().GetDatabase(_dbId).GetContainer(SubscriptionContainerName)); + _clientFactory = clientFactory; + _workflowContainer = new Lazy(() => _clientFactory.GetCosmosClient().GetDatabase(_dbId).GetContainer(WorkflowContainerName)); + _eventContainer = new Lazy(() => _clientFactory.GetCosmosClient().GetDatabase(_dbId).GetContainer(EventContainerName)); + _subscriptionContainer = new Lazy(() => _clientFactory.GetCosmosClient().GetDatabase(_dbId).GetContainer(SubscriptionContainerName)); } public async Task ClearSubscriptionToken(string eventSubscriptionId, string token) diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs index 359ef799e..3d825dd01 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs @@ -9,9 +9,9 @@ namespace WorkflowCore.Providers.Azure.Services public class CosmosDbProvisioner : ICosmosDbProvisioner { - private ICosmosDbClient _client; + private ICosmosClientFactory _client; - public CosmosDbProvisioner(ICosmosDbClient client, ILoggerFactory loggerFactory) + public CosmosDbProvisioner(ICosmosClientFactory client, ILoggerFactory loggerFactory) { _client = client; } From 15df8315b0e0bb96fa1bedb1a3dcdde5f46dd6c4 Mon Sep 17 00:00:00 2001 From: glucaci Date: Mon, 19 Apr 2021 09:49:04 +0300 Subject: [PATCH 120/342] Fix suspended workflow counter --- ReleaseNotes/3.4.0.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ReleaseNotes/3.4.0.md b/ReleaseNotes/3.4.0.md index ca724c4b2..e3708be5d 100644 --- a/ReleaseNotes/3.4.0.md +++ b/ReleaseNotes/3.4.0.md @@ -38,18 +38,27 @@ public class MetricsMiddleware : IWorkflowMiddleware switch (workflow.Status) { case WorkflowStatus.Complete: - if (_suspendedWorkflows.TryRemove(workflow.Id)) - { - _suspended.Dec(); - } + TryDecrementSuspended(workflow); _completed.Inc(); break; case WorkflowStatus.Suspended: + _suspendedWorkflows.Add(workflow.Id); _suspended.Inc(); break; + default: + TryDecrementSuspended(workflow); + break; } return next(); } + + private void TryDecrementSuspended(WorkflowInstance workflow) + { + if (_suspendedWorkflows.TryRemove(workflow.Id)) + { + _suspended.Dec(); + } + } } ``` \ No newline at end of file From 301b9fd7aac62eb280ae078475e32d3915da77c2 Mon Sep 17 00:00:00 2001 From: glucaci Date: Mon, 19 Apr 2021 10:54:05 +0300 Subject: [PATCH 121/342] Add draft API --- .../Interface/Persistence/ITransaction.cs | 10 ++++++++++ .../Interface/Persistence/IWorkflowRepository.cs | 2 +- src/WorkflowCore/Services/WorkflowController.cs | 4 ++-- .../Services/MongoPersistenceProvider.cs | 12 ++++++++++-- .../Services/MongoTransaction.cs | 15 +++++++++++++++ 5 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 src/WorkflowCore/Interface/Persistence/ITransaction.cs create mode 100644 src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoTransaction.cs diff --git a/src/WorkflowCore/Interface/Persistence/ITransaction.cs b/src/WorkflowCore/Interface/Persistence/ITransaction.cs new file mode 100644 index 000000000..cbb51e778 --- /dev/null +++ b/src/WorkflowCore/Interface/Persistence/ITransaction.cs @@ -0,0 +1,10 @@ +namespace WorkflowCore.Interface +{ + public interface ITransaction + { + /// + /// The transaction session specific for each storage provider. + /// + object Session { get; } + } +} \ No newline at end of file diff --git a/src/WorkflowCore/Interface/Persistence/IWorkflowRepository.cs b/src/WorkflowCore/Interface/Persistence/IWorkflowRepository.cs index 333423561..62545ba6f 100644 --- a/src/WorkflowCore/Interface/Persistence/IWorkflowRepository.cs +++ b/src/WorkflowCore/Interface/Persistence/IWorkflowRepository.cs @@ -7,7 +7,7 @@ namespace WorkflowCore.Interface { public interface IWorkflowRepository { - Task CreateNewWorkflow(WorkflowInstance workflow); + Task CreateNewWorkflow(WorkflowInstance workflow, ITransaction transaction = null); Task PersistWorkflow(WorkflowInstance workflow); diff --git a/src/WorkflowCore/Services/WorkflowController.cs b/src/WorkflowCore/Services/WorkflowController.cs index 6edb63aa7..1fb97f821 100755 --- a/src/WorkflowCore/Services/WorkflowController.cs +++ b/src/WorkflowCore/Services/WorkflowController.cs @@ -53,7 +53,7 @@ public Task StartWorkflow(string workflowId, TData data = null, s return StartWorkflow(workflowId, null, data, reference); } - public async Task StartWorkflow(string workflowId, int? version, TData data = null, string reference=null) + public async Task StartWorkflow(string workflowId, int? version, TData data = null, string reference=null, ITransaction transaction = null) where TData : class, new() { @@ -91,7 +91,7 @@ public async Task StartWorkflow(string workflowId, int? version, await middlewareRunner.RunPreMiddleware(wf, def); } - string id = await _persistenceStore.CreateNewWorkflow(wf); + string id = await _persistenceStore.CreateNewWorkflow(wf, transaction); await _queueProvider.QueueWork(id, QueueType.Workflow); await _queueProvider.QueueWork(id, QueueType.Index); await _eventHub.PublishNotification(new WorkflowStarted diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index 041b9ae96..5a9ebab62 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -122,9 +122,17 @@ static void CreateIndexes(MongoPersistenceProvider instance) private IMongoCollection ExecutionErrors => _database.GetCollection("wfc.execution_errors"); - public async Task CreateNewWorkflow(WorkflowInstance workflow) + public async Task CreateNewWorkflow(WorkflowInstance workflow, ITransaction transaction = null) { - await WorkflowInstances.InsertOneAsync(workflow); + if (transaction?.Session is IClientSessionHandle clientSessionHandle) + { + await WorkflowInstances.InsertOneAsync(clientSessionHandle, workflow); + } + else + { + await WorkflowInstances.InsertOneAsync(workflow); + } + return workflow.Id; } diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoTransaction.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoTransaction.cs new file mode 100644 index 000000000..678e92e28 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoTransaction.cs @@ -0,0 +1,15 @@ +using MongoDB.Driver; +using WorkflowCore.Interface; + +namespace WorkflowCore.Persistence.MongoDB.Services +{ + public class MongoTransaction : ITransaction + { + public MongoTransaction(IClientSessionHandle session) + { + Session = session; + } + + public object Session { get; } + } +} \ No newline at end of file From 3348dcacb6f6d842596bff374f4339f8d5e55f18 Mon Sep 17 00:00:00 2001 From: glucaci Date: Mon, 19 Apr 2021 10:55:56 +0300 Subject: [PATCH 122/342] Remove unnecessary file --- .../Services/MongoTransaction.cs | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoTransaction.cs diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoTransaction.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoTransaction.cs deleted file mode 100644 index 678e92e28..000000000 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoTransaction.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MongoDB.Driver; -using WorkflowCore.Interface; - -namespace WorkflowCore.Persistence.MongoDB.Services -{ - public class MongoTransaction : ITransaction - { - public MongoTransaction(IClientSessionHandle session) - { - Session = session; - } - - public object Session { get; } - } -} \ No newline at end of file From b979c2156885e7e77b739ebee5d24c7a9bbc8a27 Mon Sep 17 00:00:00 2001 From: Bruce Zlata Date: Thu, 22 Apr 2021 16:47:26 +0800 Subject: [PATCH 123/342] naming to client factory --- .../Services/CosmosDbProvisioner.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs index 3d825dd01..607b4c1cd 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs @@ -9,16 +9,16 @@ namespace WorkflowCore.Providers.Azure.Services public class CosmosDbProvisioner : ICosmosDbProvisioner { - private ICosmosClientFactory _client; + private ICosmosClientFactory _clientFactory; - public CosmosDbProvisioner(ICosmosClientFactory client, ILoggerFactory loggerFactory) + public CosmosDbProvisioner(ICosmosClientFactory clientFactory, ILoggerFactory loggerFactory) { - _client = client; + _clientFactory = clientFactory; } public async Task Provision(string dbId) { - var dbResp = await _client.GetCosmosClient().CreateDatabaseIfNotExistsAsync(dbId); + var dbResp = await _clientFactory.GetCosmosClient().CreateDatabaseIfNotExistsAsync(dbId); var wfIndexPolicy = new IndexingPolicy(); wfIndexPolicy.IncludedPaths.Add(new IncludedPath { Path = @"/*" }); wfIndexPolicy.ExcludedPaths.Add(new ExcludedPath { Path = @"/ExecutionPointers/?" }); @@ -32,6 +32,5 @@ public async Task Provision(string dbId) dbResp.Database.CreateContainerIfNotExistsAsync(new ContainerProperties(CosmosDbPersistenceProvider.SubscriptionContainerName, @"/id")) ); } - } } \ No newline at end of file From fb25722923229484604821965287fbe30dee86dc Mon Sep 17 00:00:00 2001 From: Bruce Zlata Date: Thu, 22 Apr 2021 16:48:57 +0800 Subject: [PATCH 124/342] new line at the end of file --- .../Services/CosmosDbProvisioner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs index 607b4c1cd..08e51c2f4 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs @@ -33,4 +33,4 @@ public async Task Provision(string dbId) ); } } -} \ No newline at end of file +} From e3a49d2dc2a923fb80e836e8b4e0601b0248189e Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Fri, 23 Apr 2021 11:11:58 +0300 Subject: [PATCH 125/342] Add cancellationToken support Change CosmosDB methods to be more async: https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.cosmos.container.getitemlinqqueryable?view=azure-dotnet#examples --- .../Interface/Persistence/IEventRepository.cs | 13 +- .../Persistence/IPersistenceProvider.cs | 3 +- .../Persistence/ISubscriptionRepository.cs | 15 +- .../Persistence/IWorkflowRepository.cs | 11 +- .../Services/BackgroundTasks/EventConsumer.cs | 20 +- .../BackgroundTasks/WorkflowConsumer.cs | 16 +- .../MemoryPersistenceProvider.cs | 39 ++-- .../TransientMemoryPersistenceProvider.cs | 40 ++-- .../Services/SyncWorkflowRunner.cs | 4 +- .../EntityFrameworkPersistenceProvider.cs | 93 +++++----- .../Services/MongoPersistenceProvider.cs | 85 ++++----- .../Services/RavendbPersistenceProvider.cs | 81 +++++---- .../Services/DynamoPersistenceProvider.cs | 75 ++++---- .../Services/CosmosDbPersistenceProvider.cs | 171 ++++++++++++------ .../Services/RedisPersistenceProvider.cs | 45 ++--- 15 files changed, 384 insertions(+), 327 deletions(-) diff --git a/src/WorkflowCore/Interface/Persistence/IEventRepository.cs b/src/WorkflowCore/Interface/Persistence/IEventRepository.cs index 63abdd43c..75651c24b 100644 --- a/src/WorkflowCore/Interface/Persistence/IEventRepository.cs +++ b/src/WorkflowCore/Interface/Persistence/IEventRepository.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using WorkflowCore.Models; @@ -7,17 +8,17 @@ namespace WorkflowCore.Interface { public interface IEventRepository { - Task CreateEvent(Event newEvent); + Task CreateEvent(Event newEvent, CancellationToken cancellationToken = default); - Task GetEvent(string id); + Task GetEvent(string id, CancellationToken cancellationToken = default); - Task> GetRunnableEvents(DateTime asAt); + Task> GetRunnableEvents(DateTime asAt, CancellationToken cancellationToken = default); - Task> GetEvents(string eventName, string eventKey, DateTime asOf); + Task> GetEvents(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default); - Task MarkEventProcessed(string id); + Task MarkEventProcessed(string id, CancellationToken cancellationToken = default); - Task MarkEventUnprocessed(string id); + Task MarkEventUnprocessed(string id, CancellationToken cancellationToken = default); } } diff --git a/src/WorkflowCore/Interface/Persistence/IPersistenceProvider.cs b/src/WorkflowCore/Interface/Persistence/IPersistenceProvider.cs index 165dc7cbb..7bff56345 100644 --- a/src/WorkflowCore/Interface/Persistence/IPersistenceProvider.cs +++ b/src/WorkflowCore/Interface/Persistence/IPersistenceProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using WorkflowCore.Models; @@ -8,7 +9,7 @@ namespace WorkflowCore.Interface public interface IPersistenceProvider : IWorkflowRepository, ISubscriptionRepository, IEventRepository { - Task PersistErrors(IEnumerable errors); + Task PersistErrors(IEnumerable errors, CancellationToken cancellationToken = default); void EnsureStoreExists(); diff --git a/src/WorkflowCore/Interface/Persistence/ISubscriptionRepository.cs b/src/WorkflowCore/Interface/Persistence/ISubscriptionRepository.cs index c37cf2f32..2f22a45f4 100644 --- a/src/WorkflowCore/Interface/Persistence/ISubscriptionRepository.cs +++ b/src/WorkflowCore/Interface/Persistence/ISubscriptionRepository.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using WorkflowCore.Models; @@ -7,19 +8,19 @@ namespace WorkflowCore.Interface { public interface ISubscriptionRepository { - Task CreateEventSubscription(EventSubscription subscription); + Task CreateEventSubscription(EventSubscription subscription, CancellationToken cancellationToken = default); - Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf); + Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default); - Task TerminateSubscription(string eventSubscriptionId); + Task TerminateSubscription(string eventSubscriptionId, CancellationToken cancellationToken = default); - Task GetSubscription(string eventSubscriptionId); + Task GetSubscription(string eventSubscriptionId, CancellationToken cancellationToken = default); - Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf); + Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default); - Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry); + Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry, CancellationToken cancellationToken = default); - Task ClearSubscriptionToken(string eventSubscriptionId, string token); + Task ClearSubscriptionToken(string eventSubscriptionId, string token, CancellationToken cancellationToken = default); } } diff --git a/src/WorkflowCore/Interface/Persistence/IWorkflowRepository.cs b/src/WorkflowCore/Interface/Persistence/IWorkflowRepository.cs index 333423561..1da4275cd 100644 --- a/src/WorkflowCore/Interface/Persistence/IWorkflowRepository.cs +++ b/src/WorkflowCore/Interface/Persistence/IWorkflowRepository.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using WorkflowCore.Models; @@ -7,18 +8,18 @@ namespace WorkflowCore.Interface { public interface IWorkflowRepository { - Task CreateNewWorkflow(WorkflowInstance workflow); + Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default); - Task PersistWorkflow(WorkflowInstance workflow); + Task PersistWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default); - Task> GetRunnableInstances(DateTime asAt); + Task> GetRunnableInstances(DateTime asAt, CancellationToken cancellationToken = default); [Obsolete] Task> GetWorkflowInstances(WorkflowStatus? status, string type, DateTime? createdFrom, DateTime? createdTo, int skip, int take); - Task GetWorkflowInstance(string Id); + Task GetWorkflowInstance(string Id, CancellationToken cancellationToken = default); - Task> GetWorkflowInstances(IEnumerable ids); + Task> GetWorkflowInstances(IEnumerable ids, CancellationToken cancellationToken = default); } } diff --git a/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs index bdd730fca..888ff8ed0 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs @@ -42,7 +42,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance try { cancellationToken.ThrowIfCancellationRequested(); - var evt = await _eventRepository.GetEvent(itemId); + var evt = await _eventRepository.GetEvent(itemId, cancellationToken); if (evt.IsProcessed) { _greylist.Add($"evt:{evt.Id}"); @@ -53,18 +53,18 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance IEnumerable subs = null; if (evt.EventData is ActivityResult) { - var activity = await _subscriptionRepository.GetSubscription((evt.EventData as ActivityResult).SubscriptionId); + var activity = await _subscriptionRepository.GetSubscription((evt.EventData as ActivityResult).SubscriptionId, cancellationToken); if (activity == null) { Logger.LogWarning($"Activity already processed - {(evt.EventData as ActivityResult).SubscriptionId}"); - await _eventRepository.MarkEventProcessed(itemId); + await _eventRepository.MarkEventProcessed(itemId, cancellationToken); return; } subs = new List() { activity }; } else { - subs = await _subscriptionRepository.GetSubscriptions(evt.EventName, evt.EventKey, evt.EventTime); + subs = await _subscriptionRepository.GetSubscriptions(evt.EventName, evt.EventKey, evt.EventTime, cancellationToken); } var toQueue = new HashSet(); @@ -74,7 +74,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance complete = complete && await SeedSubscription(evt, sub, toQueue, cancellationToken); if (complete) - await _eventRepository.MarkEventProcessed(itemId); + await _eventRepository.MarkEventProcessed(itemId, cancellationToken); foreach (var eventId in toQueue) await QueueProvider.QueueWork(eventId, QueueType.Event); @@ -88,12 +88,12 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance private async Task SeedSubscription(Event evt, EventSubscription sub, HashSet toQueue, CancellationToken cancellationToken) { - foreach (var eventId in await _eventRepository.GetEvents(sub.EventName, sub.EventKey, sub.SubscribeAsOf)) + foreach (var eventId in await _eventRepository.GetEvents(sub.EventName, sub.EventKey, sub.SubscribeAsOf, cancellationToken)) { if (eventId == evt.Id) continue; - var siblingEvent = await _eventRepository.GetEvent(eventId); + var siblingEvent = await _eventRepository.GetEvent(eventId, cancellationToken); if ((!siblingEvent.IsProcessed) && (siblingEvent.EventTime < evt.EventTime)) { await QueueProvider.QueueWork(eventId, QueueType.Event); @@ -112,7 +112,7 @@ private async Task SeedSubscription(Event evt, EventSubscription sub, Hash try { - var workflow = await _workflowRepository.GetWorkflowInstance(sub.WorkflowId); + var workflow = await _workflowRepository.GetWorkflowInstance(sub.WorkflowId, cancellationToken); IEnumerable pointers = null; if (!string.IsNullOrEmpty(sub.ExecutionPointerId)) @@ -127,8 +127,8 @@ private async Task SeedSubscription(Event evt, EventSubscription sub, Hash p.Active = true; } workflow.NextExecution = 0; - await _workflowRepository.PersistWorkflow(workflow); - await _subscriptionRepository.TerminateSubscription(sub.Id); + await _workflowRepository.PersistWorkflow(workflow, cancellationToken); + await _subscriptionRepository.TerminateSubscription(sub.Id, cancellationToken); return true; } catch (Exception ex) diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index 6ce3776b5..36327a28f 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -43,7 +43,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance try { cancellationToken.ThrowIfCancellationRequested(); - workflow = await _persistenceStore.GetWorkflowInstance(itemId); + workflow = await _persistenceStore.GetWorkflowInstance(itemId, cancellationToken); if (workflow.Status == WorkflowStatus.Runnable) { try @@ -52,7 +52,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance } finally { - await _persistenceStore.PersistWorkflow(workflow); + await _persistenceStore.PersistWorkflow(workflow, cancellationToken); await QueueProvider.QueueWork(itemId, QueueType.Index); _greylist.Remove($"wf:{itemId}"); } @@ -65,10 +65,10 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance { foreach (var sub in result.Subscriptions) { - await SubscribeEvent(sub, _persistenceStore); + await SubscribeEvent(sub, _persistenceStore, cancellationToken); } - await _persistenceStore.PersistErrors(result.Errors); + await _persistenceStore.PersistErrors(result.Errors, cancellationToken); var readAheadTicks = _datetimeProvider.UtcNow.Add(Options.PollInterval).Ticks; @@ -81,18 +81,18 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance } - private async Task SubscribeEvent(EventSubscription subscription, IPersistenceProvider persistenceStore) + private async Task SubscribeEvent(EventSubscription subscription, IPersistenceProvider persistenceStore, CancellationToken cancellationToken) { //TODO: move to own class Logger.LogDebug("Subscribing to event {0} {1} for workflow {2} step {3}", subscription.EventName, subscription.EventKey, subscription.WorkflowId, subscription.StepId); - await persistenceStore.CreateEventSubscription(subscription); + await persistenceStore.CreateEventSubscription(subscription, cancellationToken); if (subscription.EventName != Event.EventTypeActivity) { - var events = await persistenceStore.GetEvents(subscription.EventName, subscription.EventKey, subscription.SubscribeAsOf); + var events = await persistenceStore.GetEvents(subscription.EventName, subscription.EventKey, subscription.SubscribeAsOf, cancellationToken); foreach (var evt in events) { - await persistenceStore.MarkEventUnprocessed(evt); + await persistenceStore.MarkEventUnprocessed(evt, cancellationToken); await QueueProvider.QueueWork(evt, QueueType.Event); } } diff --git a/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs b/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs index fd27db8ca..468967972 100644 --- a/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs +++ b/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; @@ -24,7 +25,7 @@ public class MemoryPersistenceProvider : ISingletonMemoryProvider private readonly List _events = new List(); private readonly List _errors = new List(); - public async Task CreateNewWorkflow(WorkflowInstance workflow) + public async Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken _ = default) { lock (_instances) { @@ -34,7 +35,7 @@ public async Task CreateNewWorkflow(WorkflowInstance workflow) } } - public async Task PersistWorkflow(WorkflowInstance workflow) + public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken _ = default) { lock (_instances) { @@ -44,7 +45,7 @@ public async Task PersistWorkflow(WorkflowInstance workflow) } } - public async Task> GetRunnableInstances(DateTime asAt) + public async Task> GetRunnableInstances(DateTime asAt, CancellationToken _ = default) { lock (_instances) { @@ -53,7 +54,7 @@ public async Task> GetRunnableInstances(DateTime asAt) } } - public async Task GetWorkflowInstance(string Id) + public async Task GetWorkflowInstance(string Id, CancellationToken _ = default) { lock (_instances) { @@ -61,7 +62,7 @@ public async Task GetWorkflowInstance(string Id) } } - public async Task> GetWorkflowInstances(IEnumerable ids) + public async Task> GetWorkflowInstances(IEnumerable ids, CancellationToken _ = default) { if (ids == null) { @@ -105,7 +106,7 @@ public async Task> GetWorkflowInstances(WorkflowSt } - public async Task CreateEventSubscription(EventSubscription subscription) + public async Task CreateEventSubscription(EventSubscription subscription, CancellationToken _ = default) { lock (_subscriptions) { @@ -115,7 +116,7 @@ public async Task CreateEventSubscription(EventSubscription subscription } } - public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf) + public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf, CancellationToken _ = default) { lock (_subscriptions) { @@ -124,7 +125,7 @@ public async Task> GetSubscriptions(string eventN } } - public async Task TerminateSubscription(string eventSubscriptionId) + public async Task TerminateSubscription(string eventSubscriptionId, CancellationToken _ = default) { lock (_subscriptions) { @@ -133,7 +134,7 @@ public async Task TerminateSubscription(string eventSubscriptionId) } } - public Task GetSubscription(string eventSubscriptionId) + public Task GetSubscription(string eventSubscriptionId, CancellationToken _ = default) { lock (_subscriptions) { @@ -142,7 +143,7 @@ public Task GetSubscription(string eventSubscriptionId) } } - public Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf) + public Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf, CancellationToken _ = default) { lock (_subscriptions) { @@ -152,7 +153,7 @@ public Task GetFirstOpenSubscription(string eventName, string } } - public Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry) + public Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry, CancellationToken _ = default) { lock (_subscriptions) { @@ -165,7 +166,7 @@ public Task SetSubscriptionToken(string eventSubscriptionId, string token, } } - public Task ClearSubscriptionToken(string eventSubscriptionId, string token) + public Task ClearSubscriptionToken(string eventSubscriptionId, string token, CancellationToken _ = default) { lock (_subscriptions) { @@ -184,7 +185,7 @@ public void EnsureStoreExists() { } - public async Task CreateEvent(Event newEvent) + public async Task CreateEvent(Event newEvent, CancellationToken _ = default) { lock (_events) { @@ -194,7 +195,7 @@ public async Task CreateEvent(Event newEvent) } } - public async Task MarkEventProcessed(string id) + public async Task MarkEventProcessed(string id, CancellationToken _ = default) { lock (_events) { @@ -204,7 +205,7 @@ public async Task MarkEventProcessed(string id) } } - public async Task> GetRunnableEvents(DateTime asAt) + public async Task> GetRunnableEvents(DateTime asAt, CancellationToken _ = default) { lock (_events) { @@ -216,7 +217,7 @@ public async Task> GetRunnableEvents(DateTime asAt) } } - public async Task GetEvent(string id) + public async Task GetEvent(string id, CancellationToken _ = default) { lock (_events) { @@ -224,7 +225,7 @@ public async Task GetEvent(string id) } } - public async Task> GetEvents(string eventName, string eventKey, DateTime asOf) + public async Task> GetEvents(string eventName, string eventKey, DateTime asOf, CancellationToken _ = default) { lock (_events) { @@ -236,7 +237,7 @@ public async Task> GetEvents(string eventName, string eventK } } - public async Task MarkEventUnprocessed(string id) + public async Task MarkEventUnprocessed(string id, CancellationToken _ = default) { lock (_events) { @@ -248,7 +249,7 @@ public async Task MarkEventUnprocessed(string id) } } - public async Task PersistErrors(IEnumerable errors) + public async Task PersistErrors(IEnumerable errors, CancellationToken _ = default) { lock (errors) { diff --git a/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs b/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs index 6b3084a89..62a0a8aba 100644 --- a/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs +++ b/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using System.Text; +using System.Threading; using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; @@ -16,45 +16,45 @@ public TransientMemoryPersistenceProvider(ISingletonMemoryProvider innerService) _innerService = innerService; } - public Task CreateEvent(Event newEvent) => _innerService.CreateEvent(newEvent); + public Task CreateEvent(Event newEvent, CancellationToken _ = default) => _innerService.CreateEvent(newEvent); - public Task CreateEventSubscription(EventSubscription subscription) => _innerService.CreateEventSubscription(subscription); + public Task CreateEventSubscription(EventSubscription subscription, CancellationToken _ = default) => _innerService.CreateEventSubscription(subscription); - public Task CreateNewWorkflow(WorkflowInstance workflow) => _innerService.CreateNewWorkflow(workflow); + public Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken _ = default) => _innerService.CreateNewWorkflow(workflow); public void EnsureStoreExists() => _innerService.EnsureStoreExists(); - public Task GetEvent(string id) => _innerService.GetEvent(id); + public Task GetEvent(string id, CancellationToken _ = default) => _innerService.GetEvent(id); - public Task> GetEvents(string eventName, string eventKey, DateTime asOf) => _innerService.GetEvents(eventName, eventKey, asOf); + public Task> GetEvents(string eventName, string eventKey, DateTime asOf, CancellationToken _ = default) => _innerService.GetEvents(eventName, eventKey, asOf); - public Task> GetRunnableEvents(DateTime asAt) => _innerService.GetRunnableEvents(asAt); + public Task> GetRunnableEvents(DateTime asAt, CancellationToken _ = default) => _innerService.GetRunnableEvents(asAt); - public Task> GetRunnableInstances(DateTime asAt) => _innerService.GetRunnableInstances(asAt); + public Task> GetRunnableInstances(DateTime asAt, CancellationToken _ = default) => _innerService.GetRunnableInstances(asAt); - public Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf) => _innerService.GetSubscriptions(eventName, eventKey, asOf); + public Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf, CancellationToken _ = default) => _innerService.GetSubscriptions(eventName, eventKey, asOf); - public Task GetWorkflowInstance(string Id) => _innerService.GetWorkflowInstance(Id); + public Task GetWorkflowInstance(string Id, CancellationToken _ = default) => _innerService.GetWorkflowInstance(Id); - public Task> GetWorkflowInstances(IEnumerable ids) => _innerService.GetWorkflowInstances(ids); + public Task> GetWorkflowInstances(IEnumerable ids, CancellationToken _ = default) => _innerService.GetWorkflowInstances(ids); public Task> GetWorkflowInstances(WorkflowStatus? status, string type, DateTime? createdFrom, DateTime? createdTo, int skip, int take) => _innerService.GetWorkflowInstances(status, type, createdFrom, createdTo, skip, take); - public Task MarkEventProcessed(string id) => _innerService.MarkEventProcessed(id); + public Task MarkEventProcessed(string id, CancellationToken _ = default) => _innerService.MarkEventProcessed(id); - public Task MarkEventUnprocessed(string id) => _innerService.MarkEventUnprocessed(id); + public Task MarkEventUnprocessed(string id, CancellationToken _ = default) => _innerService.MarkEventUnprocessed(id); - public Task PersistErrors(IEnumerable errors) => _innerService.PersistErrors(errors); + public Task PersistErrors(IEnumerable errors, CancellationToken _ = default) => _innerService.PersistErrors(errors); - public Task PersistWorkflow(WorkflowInstance workflow) => _innerService.PersistWorkflow(workflow); + public Task PersistWorkflow(WorkflowInstance workflow, CancellationToken _ = default) => _innerService.PersistWorkflow(workflow); - public Task TerminateSubscription(string eventSubscriptionId) => _innerService.TerminateSubscription(eventSubscriptionId); - public Task GetSubscription(string eventSubscriptionId) => _innerService.GetSubscription(eventSubscriptionId); + public Task TerminateSubscription(string eventSubscriptionId, CancellationToken _ = default) => _innerService.TerminateSubscription(eventSubscriptionId); + public Task GetSubscription(string eventSubscriptionId, CancellationToken _ = default) => _innerService.GetSubscription(eventSubscriptionId); - public Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf) => _innerService.GetFirstOpenSubscription(eventName, eventKey, asOf); + public Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf, CancellationToken _ = default) => _innerService.GetFirstOpenSubscription(eventName, eventKey, asOf); - public Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry) => _innerService.SetSubscriptionToken(eventSubscriptionId, token, workerId, expiry); + public Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry, CancellationToken _ = default) => _innerService.SetSubscriptionToken(eventSubscriptionId, token, workerId, expiry); - public Task ClearSubscriptionToken(string eventSubscriptionId, string token) => _innerService.ClearSubscriptionToken(eventSubscriptionId, token); + public Task ClearSubscriptionToken(string eventSubscriptionId, string token, CancellationToken _ = default) => _innerService.ClearSubscriptionToken(eventSubscriptionId, token); } } diff --git a/src/WorkflowCore/Services/SyncWorkflowRunner.cs b/src/WorkflowCore/Services/SyncWorkflowRunner.cs index 293c976a0..5a9b7d5b5 100644 --- a/src/WorkflowCore/Services/SyncWorkflowRunner.cs +++ b/src/WorkflowCore/Services/SyncWorkflowRunner.cs @@ -74,7 +74,7 @@ public async Task RunWorkflowSync(string workflowId, in var id = Guid.NewGuid().ToString(); if (persistSate) - id = await _persistenceStore.CreateNewWorkflow(wf); + id = await _persistenceStore.CreateNewWorkflow(wf, token); else wf.Id = id; @@ -91,7 +91,7 @@ public async Task RunWorkflowSync(string workflowId, in { await _executor.Execute(wf); if (persistSate) - await _persistenceStore.PersistWorkflow(wf); + await _persistenceStore.PersistWorkflow(wf, token); } } finally diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs index 3af7354de..e0c7082fd 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs @@ -2,15 +2,12 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.Extensions.DependencyInjection; using WorkflowCore.Interface; using WorkflowCore.Persistence.EntityFramework.Models; using WorkflowCore.Models; -using Microsoft.EntityFrameworkCore.Metadata.Builders; using WorkflowCore.Persistence.EntityFramework.Interfaces; +using System.Threading; namespace WorkflowCore.Persistence.EntityFramework.Services { @@ -27,31 +24,31 @@ public EntityFrameworkPersistenceProvider(IWorkflowDbContextFactory contextFacto _canMigrateDB = canMigrateDB; } - public async Task CreateEventSubscription(EventSubscription subscription) + public async Task CreateEventSubscription(EventSubscription subscription, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { subscription.Id = Guid.NewGuid().ToString(); var persistable = subscription.ToPersistable(); var result = db.Set().Add(persistable); - await db.SaveChangesAsync(); + await db.SaveChangesAsync(cancellationToken); return subscription.Id; } } - public async Task CreateNewWorkflow(WorkflowInstance workflow) + public async Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { workflow.Id = Guid.NewGuid().ToString(); var persistable = workflow.ToPersistable(); var result = db.Set().Add(persistable); - await db.SaveChangesAsync(); + await db.SaveChangesAsync(cancellationToken); return workflow.Id; } } - public async Task> GetRunnableInstances(DateTime asAt) + public async Task> GetRunnableInstances(DateTime asAt, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { @@ -59,7 +56,7 @@ public async Task> GetRunnableInstances(DateTime asAt) var raw = await db.Set() .Where(x => x.NextExecution.HasValue && (x.NextExecution <= now) && (x.Status == WorkflowStatus.Runnable)) .Select(x => x.InstanceId) - .ToListAsync(); + .ToListAsync(cancellationToken); return raw.Select(s => s.ToString()).ToList(); } @@ -97,7 +94,7 @@ public async Task> GetWorkflowInstances(WorkflowSt } } - public async Task GetWorkflowInstance(string Id) + public async Task GetWorkflowInstance(string Id, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { @@ -106,7 +103,7 @@ public async Task GetWorkflowInstance(string Id) .Include(wf => wf.ExecutionPointers) .ThenInclude(ep => ep.ExtensionAttributes) .Include(wf => wf.ExecutionPointers) - .FirstAsync(x => x.InstanceId == uid); + .FirstAsync(x => x.InstanceId == uid, cancellationToken); if (raw == null) return null; @@ -115,7 +112,7 @@ public async Task GetWorkflowInstance(string Id) } } - public async Task> GetWorkflowInstances(IEnumerable ids) + public async Task> GetWorkflowInstances(IEnumerable ids, CancellationToken cancellationToken = default) { if (ids == null) { @@ -131,11 +128,11 @@ public async Task> GetWorkflowInstances(IEnumerabl .Include(wf => wf.ExecutionPointers) .Where(x => uids.Contains(x.InstanceId)); - return (await raw.ToListAsync()).Select(i => i.ToWorkflowInstance()); + return (await raw.ToListAsync(cancellationToken)).Select(i => i.ToWorkflowInstance()); } } - public async Task PersistWorkflow(WorkflowInstance workflow) + public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { @@ -146,21 +143,21 @@ public async Task PersistWorkflow(WorkflowInstance workflow) .ThenInclude(ep => ep.ExtensionAttributes) .Include(wf => wf.ExecutionPointers) .AsTracking() - .FirstAsync(); + .FirstAsync(cancellationToken); var persistable = workflow.ToPersistable(existingEntity); - await db.SaveChangesAsync(); + await db.SaveChangesAsync(cancellationToken); } } - public async Task TerminateSubscription(string eventSubscriptionId) + public async Task TerminateSubscription(string eventSubscriptionId, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { var uid = new Guid(eventSubscriptionId); - var existing = await db.Set().FirstAsync(x => x.SubscriptionId == uid); + var existing = await db.Set().FirstAsync(x => x.SubscriptionId == uid, cancellationToken); db.Set().Remove(existing); - await db.SaveChangesAsync(); + await db.SaveChangesAsync(cancellationToken); } } @@ -182,38 +179,38 @@ public virtual void EnsureStoreExists() } } - public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf) + public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { asOf = asOf.ToUniversalTime(); var raw = await db.Set() .Where(x => x.EventName == eventName && x.EventKey == eventKey && x.SubscribeAsOf <= asOf) - .ToListAsync(); + .ToListAsync(cancellationToken); return raw.Select(item => item.ToEventSubscription()).ToList(); } } - public async Task CreateEvent(Event newEvent) + public async Task CreateEvent(Event newEvent, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { newEvent.Id = Guid.NewGuid().ToString(); var persistable = newEvent.ToPersistable(); var result = db.Set().Add(persistable); - await db.SaveChangesAsync(); + await db.SaveChangesAsync(cancellationToken); return newEvent.Id; } } - public async Task GetEvent(string id) + public async Task GetEvent(string id, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { Guid uid = new Guid(id); var raw = await db.Set() - .FirstAsync(x => x.EventId == uid); + .FirstAsync(x => x.EventId == uid, cancellationToken); if (raw == null) return null; @@ -222,7 +219,7 @@ public async Task GetEvent(string id) } } - public async Task> GetRunnableEvents(DateTime asAt) + public async Task> GetRunnableEvents(DateTime asAt, CancellationToken cancellationToken = default) { var now = asAt.ToUniversalTime(); using (var db = ConstructDbContext()) @@ -232,13 +229,13 @@ public async Task> GetRunnableEvents(DateTime asAt) .Where(x => !x.IsProcessed) .Where(x => x.EventTime <= now) .Select(x => x.EventId) - .ToListAsync(); + .ToListAsync(cancellationToken); return raw.Select(s => s.ToString()).ToList(); } } - public async Task MarkEventProcessed(string id) + public async Task MarkEventProcessed(string id, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { @@ -246,14 +243,14 @@ public async Task MarkEventProcessed(string id) var existingEntity = await db.Set() .Where(x => x.EventId == uid) .AsTracking() - .FirstAsync(); + .FirstAsync(cancellationToken); existingEntity.IsProcessed = true; - await db.SaveChangesAsync(); + await db.SaveChangesAsync(cancellationToken); } } - public async Task> GetEvents(string eventName, string eventKey, DateTime asOf) + public async Task> GetEvents(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken) { using (var db = ConstructDbContext()) { @@ -261,7 +258,7 @@ public async Task> GetEvents(string eventName, string eventK .Where(x => x.EventName == eventName && x.EventKey == eventKey) .Where(x => x.EventTime >= asOf) .Select(x => x.EventId) - .ToListAsync(); + .ToListAsync(cancellationToken); var result = new List(); @@ -272,7 +269,7 @@ public async Task> GetEvents(string eventName, string eventK } } - public async Task MarkEventUnprocessed(string id) + public async Task MarkEventUnprocessed(string id, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { @@ -280,14 +277,14 @@ public async Task MarkEventUnprocessed(string id) var existingEntity = await db.Set() .Where(x => x.EventId == uid) .AsTracking() - .FirstAsync(); + .FirstAsync(cancellationToken); existingEntity.IsProcessed = false; - await db.SaveChangesAsync(); + await db.SaveChangesAsync(cancellationToken); } } - public async Task PersistErrors(IEnumerable errors) + public async Task PersistErrors(IEnumerable errors, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { @@ -298,7 +295,7 @@ public async Task PersistErrors(IEnumerable errors) { db.Set().Add(error.ToPersistable()); } - await db.SaveChangesAsync(); + await db.SaveChangesAsync(cancellationToken); } } @@ -309,28 +306,28 @@ private WorkflowDbContext ConstructDbContext() return _contextFactory.Build(); } - public async Task GetSubscription(string eventSubscriptionId) + public async Task GetSubscription(string eventSubscriptionId, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { var uid = new Guid(eventSubscriptionId); - var raw = await db.Set().FirstOrDefaultAsync(x => x.SubscriptionId == uid); + var raw = await db.Set().FirstOrDefaultAsync(x => x.SubscriptionId == uid, cancellationToken); return raw?.ToEventSubscription(); } } - public async Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf) + public async Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { - var raw = await db.Set().FirstOrDefaultAsync(x => x.EventName == eventName && x.EventKey == eventKey && x.SubscribeAsOf <= asOf && x.ExternalToken == null); + var raw = await db.Set().FirstOrDefaultAsync(x => x.EventName == eventName && x.EventKey == eventKey && x.SubscribeAsOf <= asOf && x.ExternalToken == null, cancellationToken); return raw?.ToEventSubscription(); } } - public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry) + public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { @@ -338,18 +335,18 @@ public async Task SetSubscriptionToken(string eventSubscriptionId, string var existingEntity = await db.Set() .Where(x => x.SubscriptionId == uid) .AsTracking() - .FirstAsync(); + .FirstAsync(cancellationToken); existingEntity.ExternalToken = token; existingEntity.ExternalWorkerId = workerId; existingEntity.ExternalTokenExpiry = expiry; - await db.SaveChangesAsync(); + await db.SaveChangesAsync(cancellationToken); return true; } } - public async Task ClearSubscriptionToken(string eventSubscriptionId, string token) + public async Task ClearSubscriptionToken(string eventSubscriptionId, string token, CancellationToken cancellationToken = default) { using (var db = ConstructDbContext()) { @@ -357,7 +354,7 @@ public async Task ClearSubscriptionToken(string eventSubscriptionId, string toke var existingEntity = await db.Set() .Where(x => x.SubscriptionId == uid) .AsTracking() - .FirstAsync(); + .FirstAsync(cancellationToken); if (existingEntity.ExternalToken != token) throw new InvalidOperationException(); @@ -365,7 +362,7 @@ public async Task ClearSubscriptionToken(string eventSubscriptionId, string toke existingEntity.ExternalToken = null; existingEntity.ExternalWorkerId = null; existingEntity.ExternalTokenExpiry = null; - await db.SaveChangesAsync(); + await db.SaveChangesAsync(cancellationToken); } } } diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index 041b9ae96..79e9fe5b7 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -11,6 +11,7 @@ using MongoDB.Driver.Linq; using WorkflowCore.Interface; using WorkflowCore.Models; +using System.Threading; namespace WorkflowCore.Persistence.MongoDB.Services { @@ -122,42 +123,42 @@ static void CreateIndexes(MongoPersistenceProvider instance) private IMongoCollection ExecutionErrors => _database.GetCollection("wfc.execution_errors"); - public async Task CreateNewWorkflow(WorkflowInstance workflow) + public async Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) { - await WorkflowInstances.InsertOneAsync(workflow); + await WorkflowInstances.InsertOneAsync(workflow, cancellationToken: cancellationToken); return workflow.Id; } - public async Task PersistWorkflow(WorkflowInstance workflow) + public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) { - await WorkflowInstances.ReplaceOneAsync(x => x.Id == workflow.Id, workflow); + await WorkflowInstances.ReplaceOneAsync(x => x.Id == workflow.Id, workflow, cancellationToken: cancellationToken); } - public async Task> GetRunnableInstances(DateTime asAt) + public async Task> GetRunnableInstances(DateTime asAt, CancellationToken cancellationToken = default) { var now = asAt.ToUniversalTime().Ticks; var query = WorkflowInstances .Find(x => x.NextExecution.HasValue && (x.NextExecution <= now) && (x.Status == WorkflowStatus.Runnable)) .Project(x => x.Id); - return await query.ToListAsync(); + return await query.ToListAsync(cancellationToken); } - public async Task GetWorkflowInstance(string Id) + public async Task GetWorkflowInstance(string Id, CancellationToken cancellationToken = default) { - var result = await WorkflowInstances.FindAsync(x => x.Id == Id); - return await result.FirstAsync(); + var result = await WorkflowInstances.FindAsync(x => x.Id == Id, cancellationToken: cancellationToken); + return await result.FirstAsync(cancellationToken); } - public async Task> GetWorkflowInstances(IEnumerable ids) + public async Task> GetWorkflowInstances(IEnumerable ids, CancellationToken cancellationToken = default) { if (ids == null) { return new List(); } - var result = await WorkflowInstances.FindAsync(x => ids.Contains(x.Id)); - return await result.ToListAsync(); + var result = await WorkflowInstances.FindAsync(x => ids.Contains(x.Id), cancellationToken: cancellationToken); + return await result.ToListAsync(cancellationToken); } public async Task> GetWorkflowInstances(WorkflowStatus? status, string type, DateTime? createdFrom, DateTime? createdTo, int skip, int take) @@ -179,50 +180,50 @@ public async Task> GetWorkflowInstances(WorkflowSt return await result.Skip(skip).Take(take).ToListAsync(); } - public async Task CreateEventSubscription(EventSubscription subscription) + public async Task CreateEventSubscription(EventSubscription subscription, CancellationToken cancellationToken = default) { - await EventSubscriptions.InsertOneAsync(subscription); + await EventSubscriptions.InsertOneAsync(subscription, cancellationToken: cancellationToken); return subscription.Id; } - public async Task TerminateSubscription(string eventSubscriptionId) + public async Task TerminateSubscription(string eventSubscriptionId, CancellationToken cancellationToken = default) { - await EventSubscriptions.DeleteOneAsync(x => x.Id == eventSubscriptionId); + await EventSubscriptions.DeleteOneAsync(x => x.Id == eventSubscriptionId, cancellationToken); } - public async Task GetSubscription(string eventSubscriptionId) + public async Task GetSubscription(string eventSubscriptionId, CancellationToken cancellationToken = default) { - var result = await EventSubscriptions.FindAsync(x => x.Id == eventSubscriptionId); - return await result.FirstOrDefaultAsync(); + var result = await EventSubscriptions.FindAsync(x => x.Id == eventSubscriptionId, cancellationToken: cancellationToken); + return await result.FirstOrDefaultAsync(cancellationToken); } - public async Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf) + public async Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) { var query = EventSubscriptions .Find(x => x.EventName == eventName && x.EventKey == eventKey && x.SubscribeAsOf <= asOf && x.ExternalToken == null); - return await query.FirstOrDefaultAsync(); + return await query.FirstOrDefaultAsync(cancellationToken); } - public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry) + public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry, CancellationToken cancellationToken = default) { var update = Builders.Update .Set(x => x.ExternalToken, token) .Set(x => x.ExternalTokenExpiry, expiry) .Set(x => x.ExternalWorkerId, workerId); - var result = await EventSubscriptions.UpdateOneAsync(x => x.Id == eventSubscriptionId && x.ExternalToken == null, update); + var result = await EventSubscriptions.UpdateOneAsync(x => x.Id == eventSubscriptionId && x.ExternalToken == null, update, cancellationToken: cancellationToken); return (result.ModifiedCount > 0); } - public async Task ClearSubscriptionToken(string eventSubscriptionId, string token) + public async Task ClearSubscriptionToken(string eventSubscriptionId, string token, CancellationToken cancellationToken = default) { var update = Builders.Update .Set(x => x.ExternalToken, null) .Set(x => x.ExternalTokenExpiry, null) .Set(x => x.ExternalWorkerId, null); - await EventSubscriptions.UpdateOneAsync(x => x.Id == eventSubscriptionId && x.ExternalToken == token, update); + await EventSubscriptions.UpdateOneAsync(x => x.Id == eventSubscriptionId && x.ExternalToken == token, update, cancellationToken: cancellationToken); } public void EnsureStoreExists() @@ -230,65 +231,65 @@ public void EnsureStoreExists() } - public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf) + public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) { var query = EventSubscriptions .Find(x => x.EventName == eventName && x.EventKey == eventKey && x.SubscribeAsOf <= asOf); - return await query.ToListAsync(); + return await query.ToListAsync(cancellationToken); } - public async Task CreateEvent(Event newEvent) + public async Task CreateEvent(Event newEvent, CancellationToken cancellationToken = default) { - await Events.InsertOneAsync(newEvent); + await Events.InsertOneAsync(newEvent, cancellationToken: cancellationToken); return newEvent.Id; } - public async Task GetEvent(string id) + public async Task GetEvent(string id, CancellationToken cancellationToken = default) { - var result = await Events.FindAsync(x => x.Id == id); - return await result.FirstAsync(); + var result = await Events.FindAsync(x => x.Id == id, cancellationToken: cancellationToken); + return await result.FirstAsync(cancellationToken); } - public async Task> GetRunnableEvents(DateTime asAt) + public async Task> GetRunnableEvents(DateTime asAt, CancellationToken cancellationToken = default) { var now = asAt.ToUniversalTime(); var query = Events .Find(x => !x.IsProcessed && x.EventTime <= now) .Project(x => x.Id); - return await query.ToListAsync(); + return await query.ToListAsync(cancellationToken); } - public async Task MarkEventProcessed(string id) + public async Task MarkEventProcessed(string id, CancellationToken cancellationToken = default) { var update = Builders.Update .Set(x => x.IsProcessed, true); - await Events.UpdateOneAsync(x => x.Id == id, update); + await Events.UpdateOneAsync(x => x.Id == id, update, cancellationToken: cancellationToken); } - public async Task> GetEvents(string eventName, string eventKey, DateTime asOf) + public async Task> GetEvents(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken) { var query = Events .Find(x => x.EventName == eventName && x.EventKey == eventKey && x.EventTime >= asOf) .Project(x => x.Id); - return await query.ToListAsync(); + return await query.ToListAsync(cancellationToken); } - public async Task MarkEventUnprocessed(string id) + public async Task MarkEventUnprocessed(string id, CancellationToken cancellationToken = default) { var update = Builders.Update .Set(x => x.IsProcessed, false); - await Events.UpdateOneAsync(x => x.Id == id, update); + await Events.UpdateOneAsync(x => x.Id == id, update, cancellationToken: cancellationToken); } - public async Task PersistErrors(IEnumerable errors) + public async Task PersistErrors(IEnumerable errors, CancellationToken cancellationToken = default) { if (errors.Any()) - await ExecutionErrors.InsertManyAsync(errors); + await ExecutionErrors.InsertManyAsync(errors, cancellationToken: cancellationToken); } } } diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs index 66d38b5aa..1bcaadff8 100644 --- a/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; using WorkflowCore.Interface; using WorkflowCore.Models; @@ -39,18 +40,18 @@ static void CreateIndexes(RavendbPersistenceProvider instance) } } - public async Task CreateNewWorkflow(WorkflowInstance workflow) + public async Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) { using (var session = _database.OpenAsyncSession()) { - await session.StoreAsync(workflow); + await session.StoreAsync(workflow, cancellationToken); var id = workflow.Id; - await session.SaveChangesAsync(); + await session.SaveChangesAsync(cancellationToken); return id; } } - public async Task PersistWorkflow(WorkflowInstance workflow) + public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) { using (var session = _database.OpenAsyncSession()) { @@ -65,11 +66,11 @@ public async Task PersistWorkflow(WorkflowInstance workflow) session.Advanced.Patch(workflow.Id, x => x.CreateTime, workflow.CreateTime); session.Advanced.Patch(workflow.Id, x => x.CompleteTime, workflow.CompleteTime); - await session.SaveChangesAsync(); + await session.SaveChangesAsync(cancellationToken); } } - public async Task> GetRunnableInstances(DateTime asAt) + public async Task> GetRunnableInstances(DateTime asAt, CancellationToken cancellationToken = default) { var now = asAt.ToUniversalTime().Ticks; using (var session = _database.OpenAsyncSession()) @@ -79,20 +80,20 @@ public async Task> GetRunnableInstances(DateTime asAt) && (w.Status == WorkflowStatus.Runnable) ).Select(x => x.Id); - return await l.ToListAsync(); + return await l.ToListAsync(cancellationToken); } } - public async Task GetWorkflowInstance(string Id) + public async Task GetWorkflowInstance(string Id, CancellationToken cancellationToken = default) { using (var session = _database.OpenAsyncSession()) { - var result = await session.Query().FirstOrDefaultAsync(x => x.Id == Id); + var result = await session.Query().FirstOrDefaultAsync(x => x.Id == Id, cancellationToken); return result; } } - public async Task> GetWorkflowInstances(IEnumerable ids) + public async Task> GetWorkflowInstances(IEnumerable ids, CancellationToken cancellationToken = default) { if (ids == null) { @@ -102,7 +103,7 @@ public async Task> GetWorkflowInstances(IEnumerabl using (var session = _database.OpenAsyncSession()) { var list = session.Query().Where(x => x.Id.In(ids)); - return await list.ToListAsync(); + return await list.ToListAsync(cancellationToken); } } @@ -128,18 +129,18 @@ public async Task> GetWorkflowInstances(WorkflowSt } } - public async Task CreateEventSubscription(EventSubscription subscription) + public async Task CreateEventSubscription(EventSubscription subscription, CancellationToken cancellationToken = default) { using (var session = _database.OpenAsyncSession()) { - await session.StoreAsync(subscription); + await session.StoreAsync(subscription, cancellationToken); var id = subscription.Id; - await session.SaveChangesAsync(); + await session.SaveChangesAsync(cancellationToken); return id; } } - public async Task TerminateSubscription(string eventSubscriptionId) + public async Task TerminateSubscription(string eventSubscriptionId, CancellationToken _ = default) { using (var session = _database.OpenAsyncSession()) { @@ -148,16 +149,16 @@ public async Task TerminateSubscription(string eventSubscriptionId) } } - public async Task GetSubscription(string eventSubscriptionId) + public async Task GetSubscription(string eventSubscriptionId, CancellationToken cancellationToken = default) { using (var session = _database.OpenAsyncSession()) { var result = session.Query().Where(x => x.Id == eventSubscriptionId); - return await result.FirstOrDefaultAsync(); + return await result.FirstOrDefaultAsync(cancellationToken); } } - public async Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf) + public async Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) { using (var session = _database.OpenAsyncSession()) { @@ -168,11 +169,11 @@ public async Task GetFirstOpenSubscription(string eventName, && x.ExternalToken == null ); - return await q.FirstOrDefaultAsync(); + return await q.FirstOrDefaultAsync(cancellationToken); } } - public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry) + public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry, CancellationToken cancellationToken = default) { try { @@ -187,7 +188,7 @@ public async Task SetSubscriptionToken(string eventSubscriptionId, string strbuilder.Append($"e.ExternalWorkerId = 'workerId'"); strbuilder.Append("}"); - var operation = await _database.Operations.SendAsync(new PatchByQueryOperation(strbuilder.ToString())); + var operation = await _database.Operations.SendAsync(new PatchByQueryOperation(strbuilder.ToString()), token: cancellationToken); operation.WaitForCompletion(); return true; } @@ -197,7 +198,7 @@ public async Task SetSubscriptionToken(string eventSubscriptionId, string } } - public async Task ClearSubscriptionToken(string eventSubscriptionId, string token) + public async Task ClearSubscriptionToken(string eventSubscriptionId, string token, CancellationToken cancellationToken = default) { try { @@ -212,7 +213,7 @@ public async Task ClearSubscriptionToken(string eventSubscriptionId, string toke strbuilder.Append($"e.ExternalWorkerId = null"); strbuilder.Append("}"); - var operation = await _database.Operations.SendAsync(new PatchByQueryOperation(strbuilder.ToString())); + var operation = await _database.Operations.SendAsync(new PatchByQueryOperation(strbuilder.ToString()), token: cancellationToken); operation.WaitForCompletion(); } catch (Exception e) @@ -223,7 +224,7 @@ public async Task ClearSubscriptionToken(string eventSubscriptionId, string toke public void EnsureStoreExists() { } - public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf) + public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) { using (var session = _database.OpenAsyncSession()) { @@ -233,31 +234,31 @@ public async Task> GetSubscriptions(string eventN && x.SubscribeAsOf <= asOf ); - return await q.ToListAsync(); + return await q.ToListAsync(cancellationToken); } } - public async Task CreateEvent(Event newEvent) + public async Task CreateEvent(Event newEvent, CancellationToken cancellationToken = default) { using (var session = _database.OpenAsyncSession()) { - await session.StoreAsync(newEvent); + await session.StoreAsync(newEvent, cancellationToken); var id = newEvent.Id; - await session.SaveChangesAsync(); + await session.SaveChangesAsync(cancellationToken); return id; } } - public async Task GetEvent(string id) + public async Task GetEvent(string id, CancellationToken cancellationToken = default) { using (var session = _database.OpenAsyncSession()) { var result = session.Query().Where(x => x.Id == id); - return await result.FirstAsync(); + return await result.FirstAsync(cancellationToken); } } - public async Task> GetRunnableEvents(DateTime asAt) + public async Task> GetRunnableEvents(DateTime asAt, CancellationToken cancellationToken = default) { using (var session = _database.OpenAsyncSession()) { @@ -266,21 +267,21 @@ public async Task> GetRunnableEvents(DateTime asAt) .Where(x => !x.IsProcessed && x.EventTime < now) .Select(x => x.Id); - return await result.ToListAsync(); + return await result.ToListAsync(cancellationToken); } } - public async Task MarkEventProcessed(string id) + public async Task MarkEventProcessed(string id, CancellationToken cancellationToken = default) { using (var session = _database.OpenAsyncSession()) { session.Advanced.Patch(id, x => x.IsProcessed, true); - await session.SaveChangesAsync(); + await session.SaveChangesAsync(cancellationToken); } } - public async Task> GetEvents(string eventName, string eventKey, DateTime asOf) + public async Task> GetEvents(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken) { using (var session = _database.OpenAsyncSession()) { @@ -291,25 +292,25 @@ public async Task> GetEvents(string eventName, string eventK && x.EventTime >= asOf) .Select(x => x.Id); - return await q.ToListAsync(); + return await q.ToListAsync(cancellationToken); } } - public async Task MarkEventUnprocessed(string id) + public async Task MarkEventUnprocessed(string id, CancellationToken cancellationToken = default) { using (var session = _database.OpenAsyncSession()) { session.Advanced.Patch(id, x => x.IsProcessed, false); - await session.SaveChangesAsync(); + await session.SaveChangesAsync(cancellationToken); } } - public async Task PersistErrors(IEnumerable errors) + public async Task PersistErrors(IEnumerable errors, CancellationToken cancellationToken = default) { if (errors.Any()) { - var blk = _database.BulkInsert(); + var blk = _database.BulkInsert(token: cancellationToken); foreach (var error in errors) await blk.StoreAsync(error); diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs index afc531b7a..073d85930 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs @@ -10,6 +10,7 @@ using WorkflowCore.Providers.AWS.Interface; using WorkflowCore.Interface; using WorkflowCore.Models; +using System.Threading; namespace WorkflowCore.Providers.AWS.Services { @@ -32,7 +33,7 @@ public DynamoPersistenceProvider(AWSCredentials credentials, AmazonDynamoDBConfi _provisioner = provisioner; } - public async Task CreateNewWorkflow(WorkflowInstance workflow) + public async Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) { workflow.Id = Guid.NewGuid().ToString(); @@ -43,12 +44,12 @@ public async Task CreateNewWorkflow(WorkflowInstance workflow) ConditionExpression = "attribute_not_exists(id)" }; - var response = await _client.PutItemAsync(req); + var _ = await _client.PutItemAsync(req, cancellationToken); return workflow.Id; } - public async Task PersistWorkflow(WorkflowInstance workflow) + public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) { var request = new PutItemRequest() { @@ -56,10 +57,10 @@ public async Task PersistWorkflow(WorkflowInstance workflow) Item = workflow.ToDynamoMap() }; - var response = await _client.PutItemAsync(request); + var response = await _client.PutItemAsync(request, cancellationToken); } - public async Task> GetRunnableInstances(DateTime asAt) + public async Task> GetRunnableInstances(DateTime asAt, CancellationToken cancellationToken = default) { var result = new List(); var now = asAt.ToUniversalTime().Ticks; @@ -88,7 +89,7 @@ public async Task> GetRunnableInstances(DateTime asAt) ScanIndexForward = true }; - var response = await _client.QueryAsync(request); + var response = await _client.QueryAsync(request, cancellationToken); foreach (var item in response.Items) { @@ -103,7 +104,7 @@ public Task> GetWorkflowInstances(WorkflowStatus? throw new NotImplementedException(); } - public async Task GetWorkflowInstance(string Id) + public async Task GetWorkflowInstance(string Id, CancellationToken cancellationToken = default) { var req = new GetItemRequest() { @@ -113,12 +114,12 @@ public async Task GetWorkflowInstance(string Id) { "id", new AttributeValue(Id) } } }; - var response = await _client.GetItemAsync(req); + var response = await _client.GetItemAsync(req, cancellationToken); return response.Item.ToWorkflowInstance(); } - public async Task> GetWorkflowInstances(IEnumerable ids) + public async Task> GetWorkflowInstances(IEnumerable ids, CancellationToken cancellationToken = default) { if (ids == null) { @@ -151,7 +152,7 @@ public async Task> GetWorkflowInstances(IEnumerabl BatchGetItemResponse response; do { - response = await _client.BatchGetItemAsync(request); + response = await _client.BatchGetItemAsync(request, cancellationToken); foreach (var tableResponse in response.Responses) result.AddRange(tableResponse.Value); @@ -161,7 +162,7 @@ public async Task> GetWorkflowInstances(IEnumerabl return result.Select(i => i.ToWorkflowInstance()); } - public async Task CreateEventSubscription(EventSubscription subscription) + public async Task CreateEventSubscription(EventSubscription subscription, CancellationToken cancellationToken = default) { subscription.Id = Guid.NewGuid().ToString(); @@ -172,12 +173,12 @@ public async Task CreateEventSubscription(EventSubscription subscription ConditionExpression = "attribute_not_exists(id)" }; - var response = await _client.PutItemAsync(req); + var response = await _client.PutItemAsync(req, cancellationToken); return subscription.Id; } - public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf) + public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) { var result = new List(); var asOfTicks = asOf.ToUniversalTime().Ticks; @@ -203,7 +204,7 @@ public async Task> GetSubscriptions(string eventN ScanIndexForward = true }; - var response = await _client.QueryAsync(request); + var response = await _client.QueryAsync(request, cancellationToken); foreach (var item in response.Items) { @@ -213,7 +214,7 @@ public async Task> GetSubscriptions(string eventN return result; } - public async Task TerminateSubscription(string eventSubscriptionId) + public async Task TerminateSubscription(string eventSubscriptionId, CancellationToken cancellationToken = default) { var request = new DeleteItemRequest() { @@ -223,10 +224,10 @@ public async Task TerminateSubscription(string eventSubscriptionId) { "id", new AttributeValue(eventSubscriptionId) } } }; - await _client.DeleteItemAsync(request); + await _client.DeleteItemAsync(request, cancellationToken); } - public async Task CreateEvent(Event newEvent) + public async Task CreateEvent(Event newEvent, CancellationToken cancellationToken = default) { newEvent.Id = Guid.NewGuid().ToString(); @@ -237,12 +238,12 @@ public async Task CreateEvent(Event newEvent) ConditionExpression = "attribute_not_exists(id)" }; - var response = await _client.PutItemAsync(req); + var _ = await _client.PutItemAsync(req, cancellationToken); return newEvent.Id; } - public async Task GetEvent(string id) + public async Task GetEvent(string id, CancellationToken cancellationToken = default) { var req = new GetItemRequest() { @@ -252,12 +253,12 @@ public async Task GetEvent(string id) { "id", new AttributeValue(id) } } }; - var response = await _client.GetItemAsync(req); + var response = await _client.GetItemAsync(req, cancellationToken); return response.Item.ToEvent(); } - public async Task> GetRunnableEvents(DateTime asAt) + public async Task> GetRunnableEvents(DateTime asAt, CancellationToken cancellationToken = default) { var result = new List(); var now = asAt.ToUniversalTime().Ticks; @@ -281,7 +282,7 @@ public async Task> GetRunnableEvents(DateTime asAt) ScanIndexForward = true }; - var response = await _client.QueryAsync(request); + var response = await _client.QueryAsync(request, cancellationToken); foreach (var item in response.Items) { @@ -291,7 +292,7 @@ public async Task> GetRunnableEvents(DateTime asAt) return result; } - public async Task> GetEvents(string eventName, string eventKey, DateTime asOf) + public async Task> GetEvents(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken) { var result = new List(); var asOfTicks = asOf.ToUniversalTime().Ticks; @@ -317,7 +318,7 @@ public async Task> GetEvents(string eventName, string eventK ScanIndexForward = true }; - var response = await _client.QueryAsync(request); + var response = await _client.QueryAsync(request, cancellationToken); foreach (var item in response.Items) { @@ -327,7 +328,7 @@ public async Task> GetEvents(string eventName, string eventK return result; } - public async Task MarkEventProcessed(string id) + public async Task MarkEventProcessed(string id, CancellationToken cancellationToken = default) { var request = new UpdateItemRequest() { @@ -338,10 +339,10 @@ public async Task MarkEventProcessed(string id) }, UpdateExpression = "REMOVE not_processed" }; - await _client.UpdateItemAsync(request); + await _client.UpdateItemAsync(request, cancellationToken); } - public async Task MarkEventUnprocessed(string id) + public async Task MarkEventUnprocessed(string id, CancellationToken cancellationToken = default) { var request = new UpdateItemRequest() { @@ -356,10 +357,10 @@ public async Task MarkEventUnprocessed(string id) { ":n" , new AttributeValue() { N = 1.ToString() } } } }; - await _client.UpdateItemAsync(request); + await _client.UpdateItemAsync(request, cancellationToken); } - public Task PersistErrors(IEnumerable errors) + public Task PersistErrors(IEnumerable errors, CancellationToken _ = default) { //TODO return Task.CompletedTask; @@ -370,7 +371,7 @@ public void EnsureStoreExists() _provisioner.ProvisionTables().Wait(); } - public async Task GetSubscription(string eventSubscriptionId) + public async Task GetSubscription(string eventSubscriptionId, CancellationToken cancellationToken = default) { var req = new GetItemRequest() { @@ -380,12 +381,12 @@ public async Task GetSubscription(string eventSubscriptionId) { "id", new AttributeValue(eventSubscriptionId) } } }; - var response = await _client.GetItemAsync(req); + var response = await _client.GetItemAsync(req, cancellationToken); return response.Item.ToEventSubscription(); } - public async Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf) + public async Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) { var result = new List(); var asOfTicks = asOf.ToUniversalTime().Ticks; @@ -413,7 +414,7 @@ public async Task GetFirstOpenSubscription(string eventName, ScanIndexForward = true }; - var response = await _client.QueryAsync(request); + var response = await _client.QueryAsync(request, cancellationToken); foreach (var item in response.Items) result.Add(item.ToEventSubscription()); @@ -421,7 +422,7 @@ public async Task GetFirstOpenSubscription(string eventName, return result.FirstOrDefault(); } - public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry) + public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry, CancellationToken cancellationToken = default) { var request = new UpdateItemRequest() { @@ -441,7 +442,7 @@ public async Task SetSubscriptionToken(string eventSubscriptionId, string }; try { - await _client.UpdateItemAsync(request); + await _client.UpdateItemAsync(request, cancellationToken); return true; } catch (ConditionalCheckFailedException) @@ -450,7 +451,7 @@ public async Task SetSubscriptionToken(string eventSubscriptionId, string } } - public async Task ClearSubscriptionToken(string eventSubscriptionId, string token) + public async Task ClearSubscriptionToken(string eventSubscriptionId, string token, CancellationToken cancellationToken = default) { var request = new UpdateItemRequest() { @@ -467,7 +468,7 @@ public async Task ClearSubscriptionToken(string eventSubscriptionId, string toke } }; - await _client.UpdateItemAsync(request); + await _client.UpdateItemAsync(request, cancellationToken); } } } \ No newline at end of file diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs index 8ca697fc2..0b2707994 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs @@ -1,9 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; +using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos; +using Microsoft.Azure.Cosmos.Linq; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Providers.Azure.Interface; @@ -13,7 +14,6 @@ namespace WorkflowCore.Providers.Azure.Services { public class CosmosDbPersistenceProvider : IPersistenceProvider { - public const string WorkflowContainerName = "workflows"; public const string EventContainerName = "events"; public const string SubscriptionContainerName = "subscriptions"; @@ -35,7 +35,7 @@ public CosmosDbPersistenceProvider(string connectionString, string dbId, ICosmos _subscriptionContainer = new Lazy(() => _client.GetDatabase(_dbId).GetContainer(SubscriptionContainerName)); } - public async Task ClearSubscriptionToken(string eventSubscriptionId, string token) + public async Task ClearSubscriptionToken(string eventSubscriptionId, string token, CancellationToken cancellationToken = default) { var existing = await _subscriptionContainer.Value.ReadItemAsync(eventSubscriptionId, new PartitionKey(eventSubscriptionId)); @@ -45,27 +45,27 @@ public async Task ClearSubscriptionToken(string eventSubscriptionId, string toke existing.Resource.ExternalWorkerId = null; existing.Resource.ExternalTokenExpiry = null; - await _subscriptionContainer.Value.ReplaceItemAsync(existing.Resource, eventSubscriptionId); + await _subscriptionContainer.Value.ReplaceItemAsync(existing.Resource, eventSubscriptionId, cancellationToken: cancellationToken); } - public async Task CreateEvent(Event newEvent) + public async Task CreateEvent(Event newEvent, CancellationToken cancellationToken) { newEvent.Id = Guid.NewGuid().ToString(); - var result = await _eventContainer.Value.CreateItemAsync(PersistedEvent.FromInstance(newEvent)); + var result = await _eventContainer.Value.CreateItemAsync(PersistedEvent.FromInstance(newEvent), cancellationToken: cancellationToken); return result.Resource.id; } - public async Task CreateEventSubscription(EventSubscription subscription) + public async Task CreateEventSubscription(EventSubscription subscription, CancellationToken cancellationToken) { subscription.Id = Guid.NewGuid().ToString(); - var result = await _subscriptionContainer.Value.CreateItemAsync(PersistedSubscription.FromInstance(subscription)); + var result = await _subscriptionContainer.Value.CreateItemAsync(PersistedSubscription.FromInstance(subscription), cancellationToken: cancellationToken); return result.Resource.id; } - public async Task CreateNewWorkflow(WorkflowInstance workflow) + public async Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken) { workflow.Id = Guid.NewGuid().ToString(); - var result = await _workflowContainer.Value.CreateItemAsync(PersistedWorkflow.FromInstance(workflow)); + var result = await _workflowContainer.Value.CreateItemAsync(PersistedWorkflow.FromInstance(workflow), cancellationToken: cancellationToken); return result.Resource.id; } @@ -74,69 +74,120 @@ public void EnsureStoreExists() _provisioner.Provision(_dbId).Wait(); } - public async Task GetEvent(string id) + public async Task GetEvent(string id, CancellationToken cancellationToken) { - var resp = await _eventContainer.Value.ReadItemAsync(id, new PartitionKey(id)); + var resp = await _eventContainer.Value.ReadItemAsync(id, new PartitionKey(id), cancellationToken: cancellationToken); return PersistedEvent.ToInstance(resp.Resource); } - public Task> GetEvents(string eventName, string eventKey, DateTime asOf) + public async Task> GetEvents(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken) { - var data = _eventContainer.Value.GetItemLinqQueryable(true) - .Where(x => x.EventName == eventName && x.EventKey == eventKey) - .Where(x => x.EventTime >= asOf) - .Select(x => x.id); - - return Task.FromResult(data.AsEnumerable()); + var events = new List(); + using (FeedIterator feedIterator = _eventContainer.Value.GetItemLinqQueryable() + .Where(x => x.EventName == eventName && x.EventKey == eventKey) + .Where(x => x.EventTime >= asOf) + .ToFeedIterator()) + { + while (feedIterator.HasMoreResults) + { + foreach (var item in await feedIterator.ReadNextAsync(cancellationToken)) + { + events.Add(item.id); + } + } + } + + return events; } - public Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf) + public async Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken) { - var data = _subscriptionContainer.Value.GetItemLinqQueryable(true) - .FirstOrDefault(x => x.ExternalToken == null && x.EventName == eventName && x.EventKey == eventKey && x.SubscribeAsOf <= asOf); - - return Task.FromResult(PersistedSubscription.ToInstance(data)); + EventSubscription eventSubscription = null; + using (FeedIterator feedIterator = _subscriptionContainer.Value.GetItemLinqQueryable() + .Where(x => x.ExternalToken == null && x.EventName == eventName && x.EventKey == eventKey && x.SubscribeAsOf <= asOf) + .ToFeedIterator()) + { + while (feedIterator.HasMoreResults && eventSubscription == null) + { + foreach (var item in await feedIterator.ReadNextAsync(cancellationToken)) + { + eventSubscription = PersistedSubscription.ToInstance(item); + } + } + } + + return eventSubscription; } - public Task> GetRunnableEvents(DateTime asAt) + public async Task> GetRunnableEvents(DateTime asAt, CancellationToken cancellationToken) { - var data = _eventContainer.Value.GetItemLinqQueryable(true) - .Where(x => !x.IsProcessed) - .Where(x => x.EventTime <= asAt.ToUniversalTime()) - .Select(x => x.id); - - return Task.FromResult(data.AsEnumerable()); + var events = new List(); + using (FeedIterator feedIterator = _eventContainer.Value.GetItemLinqQueryable() + .Where(x => !x.IsProcessed) + .Where(x => x.EventTime <= asAt.ToUniversalTime()) + .ToFeedIterator()) + { + while (feedIterator.HasMoreResults) + { + foreach (var item in await feedIterator.ReadNextAsync(cancellationToken)) + { + events.Add(item.id); + } + } + } + + return events; } - public Task> GetRunnableInstances(DateTime asAt) + public async Task> GetRunnableInstances(DateTime asAt, CancellationToken cancellationToken) { var now = asAt.ToUniversalTime().Ticks; - var data = _workflowContainer.Value.GetItemLinqQueryable(true) - .Where(x => x.NextExecution.HasValue && (x.NextExecution <= now) && (x.Status == WorkflowStatus.Runnable)) - .Select(x => x.id); + var instances = new List(); + using (FeedIterator feedIterator = _workflowContainer.Value.GetItemLinqQueryable() + .Where(x => x.NextExecution.HasValue && (x.NextExecution <= now) && (x.Status == WorkflowStatus.Runnable)) + .ToFeedIterator()) + { + while (feedIterator.HasMoreResults) + { + foreach (var item in await feedIterator.ReadNextAsync(cancellationToken)) + { + instances.Add(item.id); + } + } + } - return Task.FromResult(data.AsEnumerable()); + return instances; } - public async Task GetSubscription(string eventSubscriptionId) + public async Task GetSubscription(string eventSubscriptionId, CancellationToken cancellationToken) { - var resp = await _subscriptionContainer.Value.ReadItemAsync(eventSubscriptionId, new PartitionKey(eventSubscriptionId)); + var resp = await _subscriptionContainer.Value.ReadItemAsync(eventSubscriptionId, new PartitionKey(eventSubscriptionId), cancellationToken: cancellationToken); return PersistedSubscription.ToInstance(resp.Resource); } - public Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf) + public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken) { - var data = _subscriptionContainer.Value.GetItemLinqQueryable(true) + var subscriptions = new List(); + using (FeedIterator feedIterator = _subscriptionContainer.Value.GetItemLinqQueryable() .Where(x => x.EventName == eventName && x.EventKey == eventKey && x.SubscribeAsOf <= asOf) - .ToList() - .Select(x => PersistedSubscription.ToInstance(x)); - return Task.FromResult(data.AsEnumerable()); + .ToFeedIterator()) + { + while (feedIterator.HasMoreResults) + { + foreach (var item in await feedIterator.ReadNextAsync(cancellationToken)) + { + subscriptions.Add(PersistedSubscription.ToInstance(item)); + } + } + } + + return subscriptions; } - public async Task GetWorkflowInstance(string Id) + public async Task GetWorkflowInstance(string Id, CancellationToken cancellationToken) { - var result = await _workflowContainer.Value.ReadItemAsync(Id, new PartitionKey(Id)); + var result = await _workflowContainer.Value.ReadItemAsync(Id, new PartitionKey(Id), cancellationToken: cancellationToken); return PersistedWorkflow.ToInstance(result.Resource); } @@ -145,51 +196,51 @@ public Task> GetWorkflowInstances(WorkflowStatus? throw new NotImplementedException(); } - public Task> GetWorkflowInstances(IEnumerable ids) + public Task> GetWorkflowInstances(IEnumerable ids, CancellationToken cancellationToken) { throw new NotImplementedException(); } - public async Task MarkEventProcessed(string id) + public async Task MarkEventProcessed(string id, CancellationToken cancellationToken) { - var evt = await _eventContainer.Value.ReadItemAsync(id, new PartitionKey(id)); + var evt = await _eventContainer.Value.ReadItemAsync(id, new PartitionKey(id), cancellationToken: cancellationToken); evt.Resource.IsProcessed = true; - await _eventContainer.Value.ReplaceItemAsync(evt.Resource, id); + await _eventContainer.Value.ReplaceItemAsync(evt.Resource, id, cancellationToken: cancellationToken); } - public async Task MarkEventUnprocessed(string id) + public async Task MarkEventUnprocessed(string id, CancellationToken cancellationToken) { - var evt = await _eventContainer.Value.ReadItemAsync(id, new PartitionKey(id)); + var evt = await _eventContainer.Value.ReadItemAsync(id, new PartitionKey(id), cancellationToken: cancellationToken); evt.Resource.IsProcessed = false; - await _eventContainer.Value.ReplaceItemAsync(evt.Resource, id); + await _eventContainer.Value.ReplaceItemAsync(evt.Resource, id, cancellationToken: cancellationToken); } - public Task PersistErrors(IEnumerable errors) + public Task PersistErrors(IEnumerable errors, CancellationToken _ = default) { return Task.CompletedTask; } - public async Task PersistWorkflow(WorkflowInstance workflow) + public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken) { - await _workflowContainer.Value.UpsertItemAsync(PersistedWorkflow.FromInstance(workflow)); + await _workflowContainer.Value.UpsertItemAsync(PersistedWorkflow.FromInstance(workflow), cancellationToken: cancellationToken); } - public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry) + public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry, CancellationToken cancellationToken) { - var sub = await _subscriptionContainer.Value.ReadItemAsync(eventSubscriptionId, new PartitionKey(eventSubscriptionId)); + var sub = await _subscriptionContainer.Value.ReadItemAsync(eventSubscriptionId, new PartitionKey(eventSubscriptionId), cancellationToken: cancellationToken); var existingEntity = sub.Resource; existingEntity.ExternalToken = token; existingEntity.ExternalWorkerId = workerId; existingEntity.ExternalTokenExpiry = expiry; - await _subscriptionContainer.Value.ReplaceItemAsync(existingEntity, eventSubscriptionId); + await _subscriptionContainer.Value.ReplaceItemAsync(existingEntity, eventSubscriptionId, cancellationToken: cancellationToken); return true; } - public async Task TerminateSubscription(string eventSubscriptionId) + public async Task TerminateSubscription(string eventSubscriptionId, CancellationToken cancellationToken) { - await _subscriptionContainer.Value.DeleteItemAsync(eventSubscriptionId, new PartitionKey(eventSubscriptionId)); + await _subscriptionContainer.Value.DeleteItemAsync(eventSubscriptionId, new PartitionKey(eventSubscriptionId), cancellationToken: cancellationToken); } } } diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs index 3e593a550..616071550 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Newtonsoft.Json; @@ -37,14 +38,14 @@ public RedisPersistenceProvider(string connectionString, string prefix, bool rem _removeComplete = removeComplete; } - public async Task CreateNewWorkflow(WorkflowInstance workflow) + public async Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken _ = default) { workflow.Id = Guid.NewGuid().ToString(); await PersistWorkflow(workflow); return workflow.Id; } - public async Task PersistWorkflow(WorkflowInstance workflow) + public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken _ = default) { var str = JsonConvert.SerializeObject(workflow, _serializerSettings); await _redis.HashSetAsync($"{_prefix}.{WORKFLOW_SET}", workflow.Id, str); @@ -59,7 +60,7 @@ public async Task PersistWorkflow(WorkflowInstance workflow) } } - public async Task> GetRunnableInstances(DateTime asAt) + public async Task> GetRunnableInstances(DateTime asAt, CancellationToken _ = default) { var result = new List(); var data = await _redis.SortedSetRangeByScoreAsync($"{_prefix}.{WORKFLOW_SET}.{RUNNABLE_INDEX}", -1, asAt.ToUniversalTime().Ticks); @@ -76,13 +77,13 @@ public Task> GetWorkflowInstances(WorkflowStatus? throw new NotImplementedException(); } - public async Task GetWorkflowInstance(string Id) + public async Task GetWorkflowInstance(string Id, CancellationToken _ = default) { var raw = await _redis.HashGetAsync($"{_prefix}.{WORKFLOW_SET}", Id); return JsonConvert.DeserializeObject(raw, _serializerSettings); } - public async Task> GetWorkflowInstances(IEnumerable ids) + public async Task> GetWorkflowInstances(IEnumerable ids, CancellationToken _ = default) { if (ids == null) { @@ -93,7 +94,7 @@ public async Task> GetWorkflowInstances(IEnumerabl return raw.Select(r => JsonConvert.DeserializeObject(r, _serializerSettings)); } - public async Task CreateEventSubscription(EventSubscription subscription) + public async Task CreateEventSubscription(EventSubscription subscription, CancellationToken _ = default) { subscription.Id = Guid.NewGuid().ToString(); var str = JsonConvert.SerializeObject(subscription, _serializerSettings); @@ -103,7 +104,7 @@ public async Task CreateEventSubscription(EventSubscription subscription return subscription.Id; } - public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf) + public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf, CancellationToken _ = default) { var result = new List(); var data = await _redis.SortedSetRangeByScoreAsync($"{_prefix}.{SUBSCRIPTION_SET}.{EVENTSLUG_INDEX}.{eventName}-{eventKey}", -1, asOf.Ticks); @@ -118,7 +119,7 @@ public async Task> GetSubscriptions(string eventN return result; } - public async Task TerminateSubscription(string eventSubscriptionId) + public async Task TerminateSubscription(string eventSubscriptionId, CancellationToken _ = default) { var existingRaw = await _redis.HashGetAsync($"{_prefix}.{SUBSCRIPTION_SET}", eventSubscriptionId); var existing = JsonConvert.DeserializeObject(existingRaw, _serializerSettings); @@ -126,18 +127,18 @@ public async Task TerminateSubscription(string eventSubscriptionId) await _redis.SortedSetRemoveAsync($"{_prefix}.{SUBSCRIPTION_SET}.{EVENTSLUG_INDEX}.{existing.EventName}-{existing.EventKey}", eventSubscriptionId); } - public async Task GetSubscription(string eventSubscriptionId) + public async Task GetSubscription(string eventSubscriptionId, CancellationToken _ = default) { var raw = await _redis.HashGetAsync($"{_prefix}.{SUBSCRIPTION_SET}", eventSubscriptionId); return JsonConvert.DeserializeObject(raw, _serializerSettings); } - public async Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf) + public async Task GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) { - return (await GetSubscriptions(eventName, eventKey, asOf)).FirstOrDefault(sub => string.IsNullOrEmpty(sub.ExternalToken)); + return (await GetSubscriptions(eventName, eventKey, asOf, cancellationToken)).FirstOrDefault(sub => string.IsNullOrEmpty(sub.ExternalToken)); } - public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry) + public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry, CancellationToken _ = default) { var item = JsonConvert.DeserializeObject(await _redis.HashGetAsync($"{_prefix}.{SUBSCRIPTION_SET}", eventSubscriptionId), _serializerSettings); if (item.ExternalToken != null) @@ -150,7 +151,7 @@ public async Task SetSubscriptionToken(string eventSubscriptionId, string return true; } - public async Task ClearSubscriptionToken(string eventSubscriptionId, string token) + public async Task ClearSubscriptionToken(string eventSubscriptionId, string token, CancellationToken _ = default) { var item = JsonConvert.DeserializeObject(await _redis.HashGetAsync($"{_prefix}.{SUBSCRIPTION_SET}", eventSubscriptionId), _serializerSettings); if (item.ExternalToken != token) @@ -162,7 +163,7 @@ public async Task ClearSubscriptionToken(string eventSubscriptionId, string toke await _redis.HashSetAsync($"{_prefix}.{SUBSCRIPTION_SET}", eventSubscriptionId, str); } - public async Task CreateEvent(Event newEvent) + public async Task CreateEvent(Event newEvent, CancellationToken _ = default) { newEvent.Id = Guid.NewGuid().ToString(); var str = JsonConvert.SerializeObject(newEvent, _serializerSettings); @@ -177,13 +178,13 @@ public async Task CreateEvent(Event newEvent) return newEvent.Id; } - public async Task GetEvent(string id) + public async Task GetEvent(string id, CancellationToken _ = default) { var raw = await _redis.HashGetAsync($"{_prefix}.{EVENT_SET}", id); return JsonConvert.DeserializeObject(raw, _serializerSettings); } - public async Task> GetRunnableEvents(DateTime asAt) + public async Task> GetRunnableEvents(DateTime asAt, CancellationToken _ = default) { var result = new List(); var data = await _redis.SortedSetRangeByScoreAsync($"{_prefix}.{EVENT_SET}.{RUNNABLE_INDEX}", -1, asAt.Ticks); @@ -194,7 +195,7 @@ public async Task> GetRunnableEvents(DateTime asAt) return result; } - public async Task> GetEvents(string eventName, string eventKey, DateTime asOf) + public async Task> GetEvents(string eventName, string eventKey, DateTime asOf, CancellationToken _ = default) { var result = new List(); var data = await _redis.SortedSetRangeByScoreAsync($"{_prefix}.{EVENT_SET}.{EVENTSLUG_INDEX}.{eventName}-{eventKey}", asOf.Ticks); @@ -205,25 +206,25 @@ public async Task> GetEvents(string eventName, string eventK return result; } - public async Task MarkEventProcessed(string id) + public async Task MarkEventProcessed(string id, CancellationToken cancellationToken = default) { - var evt = await GetEvent(id); + var evt = await GetEvent(id, cancellationToken); evt.IsProcessed = true; var str = JsonConvert.SerializeObject(evt, _serializerSettings); await _redis.HashSetAsync($"{_prefix}.{EVENT_SET}", evt.Id, str); await _redis.SortedSetRemoveAsync($"{_prefix}.{EVENT_SET}.{RUNNABLE_INDEX}", id); } - public async Task MarkEventUnprocessed(string id) + public async Task MarkEventUnprocessed(string id, CancellationToken cancellationToken = default) { - var evt = await GetEvent(id); + var evt = await GetEvent(id, cancellationToken); evt.IsProcessed = false; var str = JsonConvert.SerializeObject(evt, _serializerSettings); await _redis.HashSetAsync($"{_prefix}.{EVENT_SET}", evt.Id, str); await _redis.SortedSetAddAsync($"{_prefix}.{EVENT_SET}.{RUNNABLE_INDEX}", evt.Id, evt.EventTime.Ticks); } - public Task PersistErrors(IEnumerable errors) + public Task PersistErrors(IEnumerable errors, CancellationToken _ = default) { return Task.CompletedTask; } From ebb168996e9fbcea3be54e091312edb1529eb242 Mon Sep 17 00:00:00 2001 From: Bruce Zlata Date: Sun, 25 Apr 2021 14:23:09 +0800 Subject: [PATCH 126/342] increment the minor version number --- .../WorkflowCore.Providers.Azure.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj index cd09e101e..b2f20ddc9 100644 --- a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj +++ b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj @@ -7,15 +7,15 @@ - Provides distributed lock management on Workflow Core - Provides Queueing support on Workflow Core workflow workflowcore dlm - 3.1.0 + 3.2.0 $(PackageTargetFallback);dnxcore50 https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git Daniel Gerlag - 3.1.0.0 - 3.1.0.0 + 3.2.0.0 + 3.2.0.0 From b84c9cef62aa1b496196d117bf731fbdfe209a80 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 8 May 2021 17:01:42 -0700 Subject: [PATCH 127/342] harmonize versions --- src/Directory.Build.props | 13 +++++++++++++ src/WorkflowCore.DSL/WorkflowCore.DSL.csproj | 4 ---- src/WorkflowCore/WorkflowCore.csproj | 10 ---------- .../WorkflowCore.Users/WorkflowCore.Users.csproj | 3 --- .../WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj | 1 - .../WorkflowCore.LockProviders.SqlServer.csproj | 1 - .../WorkflowCore.Persistence.EntityFramework.csproj | 4 ---- .../WorkflowCore.Persistence.MongoDB.csproj | 4 ---- .../WorkflowCore.Persistence.MySQL.csproj | 3 --- .../WorkflowCore.Persistence.PostgreSQL.csproj | 4 ---- .../WorkflowCore.Persistence.SqlServer.csproj | 4 ---- .../WorkflowCore.Persistence.Sqlite.csproj | 4 ---- .../WorkflowCore.Providers.AWS.csproj | 3 --- .../WorkflowCore.Providers.Azure.csproj | 3 --- .../WorkflowCore.Providers.Elasticsearch.csproj | 1 - .../WorkflowCore.Providers.Redis.csproj | 5 +---- .../WorkflowCore.QueueProviders.RabbitMQ.csproj | 5 ----- .../WorkflowCore.QueueProviders.SqlServer.csproj | 2 +- 18 files changed, 15 insertions(+), 59 deletions(-) create mode 100644 src/Directory.Build.props diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 000000000..f8f086812 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,13 @@ + + + https://github.com/danielgerlag/workflow-core + https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md + git + https://github.com/danielgerlag/workflow-core.git + 3.5.0 + 3.5.0.0 + 3.5.0.0 + https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png + 3.5.0 + + diff --git a/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj b/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj index 689d95119..230286071 100644 --- a/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj +++ b/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj @@ -2,14 +2,10 @@ netstandard2.0 - 3.3.1 DSL extenstion for Workflow Core provding support for JSON and YAML workflow definitions. Daniel Gerlag WorkflowCore - https://github.com/danielgerlag/workflow-core - https://github.com/danielgerlag/workflow-core.git - git diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index a439d3bac..1457092bd 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -7,20 +7,10 @@ WorkflowCore WorkflowCore workflow;.NET;Core;state machine - https://github.com/danielgerlag/workflow-core - https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md - git - https://github.com/danielgerlag/workflow-core.git false false false Workflow Core is a light weight workflow engine targeting .NET Standard. - 3.4.0 - 3.4.0.0 - 3.4.0.0 - - https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.4.0 diff --git a/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj b/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj index 5a8c0beab..66c96f4ec 100644 --- a/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj +++ b/src/extensions/WorkflowCore.Users/WorkflowCore.Users.csproj @@ -15,9 +15,6 @@ false false Provides extensions for Workflow Core to enable human workflows. - 2.1.1 - 2.1.1.0 - 2.1.1.0 diff --git a/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj b/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj index a3fb9bbb7..f6eb6ea92 100644 --- a/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj +++ b/src/extensions/WorkflowCore.WebAPI/WorkflowCore.WebAPI.csproj @@ -14,7 +14,6 @@ false false false - 2.0.0 WebAPI wrapper for Workflow host diff --git a/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj b/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj index ceb51046d..77fbe950d 100644 --- a/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj @@ -5,7 +5,6 @@ Distributed lock provider for Workflow-core using SQL Server https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md - 2.0.0 diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index b126a9c23..39627c7c9 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -14,11 +14,7 @@ false false false - 3.1.1 Base package for Workflow-core peristence providers using entity framework - 3.1.1.0 - 3.1.1.0 - 3.1.1 diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj index b365d33f6..13df8d4aa 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj +++ b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj @@ -14,11 +14,7 @@ false false false - 3.0.4 Provides support to persist workflows running on Workflow Core to a MongoDB database. - 3.0.4.0 - 3.0.4.0 - 3.0.4 diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index a031e5fba..af6cbc18d 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -16,9 +16,6 @@ false false Provides support to persist workflows running on Workflow Core to a MySQL database. - 3.0.1 - 3.0.1.0 - 3.0.1.0 diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index bcebe0247..3aa405620 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -15,10 +15,6 @@ false false Provides support to persist workflows running on Workflow Core to a PostgreSQL database. - 3.3.0 - 3.3.0.0 - 3.3.0.0 - 3.3.0 diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index f352e79c0..38375e8e6 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -15,11 +15,7 @@ false false false - 3.3.0 Provides support to persist workflows running on Workflow Core to a SQL Server database. - 3.3.0.0 - 3.3.0.0 - 3.3.0 diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj index faa1eb934..d4c73e037 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj +++ b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj @@ -16,10 +16,6 @@ false false Provides support to persist workflows running on Workflow Core to a Sqlite database. - 3.3.0 - 3.3.0.0 - 3.3.0.0 - 3.3.0 diff --git a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj index 84eb6cb74..49b7c2916 100644 --- a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj +++ b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj @@ -11,9 +11,6 @@ https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core.git git - 3.0.2 - 3.0.2.0 - 3.0.2 diff --git a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj index b2f20ddc9..dc7e5609a 100644 --- a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj +++ b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj @@ -7,15 +7,12 @@ - Provides distributed lock management on Workflow Core - Provides Queueing support on Workflow Core workflow workflowcore dlm - 3.2.0 $(PackageTargetFallback);dnxcore50 https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git Daniel Gerlag - 3.2.0.0 - 3.2.0.0 diff --git a/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj b/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj index e4263abaf..db78bebb7 100644 --- a/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj +++ b/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj @@ -2,7 +2,6 @@ netstandard2.0 - 3.0.0 https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core.git diff --git a/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj b/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj index bdb8c6456..e35b091ff 100644 --- a/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj +++ b/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj @@ -2,14 +2,11 @@ netstandard2.0 - 3.0.2 https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md https://github.com/danielgerlag/workflow-core.git git https://github.com/danielgerlag/workflow-core - Redis providers for Workflow Core (Persistence, queueing, distributed locking and event hubs) - - 3.0.2 + Redis providers for Workflow Core (Persistence, queueing, distributed locking and event hubs) diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj index 025e83913..48041387f 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj @@ -2,7 +2,6 @@ Workflow Core RabbitMQ queue provider - 1.1.0 Daniel Gerlag netstandard2.0 WorkflowCore.QueueProviders.RabbitMQ @@ -15,11 +14,7 @@ false false false - 2.0.0 Queue provider for Workflow-core using RabbitMQ - 2.0.0.0 - 2.0.0.0 - 2.1.0 diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj index 36d7cda77..77d5e2421 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj @@ -5,7 +5,7 @@ Roberto Paterlini Queue provider for Workflow-core using SQL Server Service Broker - 1.0.3-alpha + alpha From acfb7b968d1c1a55ecb49d607fac93958922ab14 Mon Sep 17 00:00:00 2001 From: Wangyang Ding Date: Mon, 17 May 2021 18:10:16 +0800 Subject: [PATCH 128/342] support deep data transmission --- .../Services/DefinitionLoader.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index b057b223a..0be4618c5 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -217,13 +217,22 @@ private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, Wo var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { stepParameter }, typeof(object), output.Value); var dataParameter = Expression.Parameter(dataType, "data"); - Expression targetProperty; + Expression targetProperty = dataParameter; // Check if our datatype has a matching property - var propertyInfo = dataType.GetProperty(output.Key); - if (propertyInfo != null) + + PropertyInfo propertyInfo = null; + String[] paths = output.Key.Split('.'); + foreach(String propertyName in paths) { - targetProperty = Expression.Property(dataParameter, propertyInfo); + if(targetProperty!=null) + { + targetProperty = Expression.Property(targetProperty, propertyName); + } + } + + if (targetProperty != null) + { var targetExpr = Expression.Lambda(targetProperty, dataParameter); step.Outputs.Add(new MemberMapParameter(sourceExpr, targetExpr)); } From c47d7754f1b7d0482d1497ff34c1db65652176d3 Mon Sep 17 00:00:00 2001 From: Wangyang Ding Date: Mon, 17 May 2021 18:13:58 +0800 Subject: [PATCH 129/342] support deep data transmission --- src/WorkflowCore.DSL/Services/DefinitionLoader.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index 0be4618c5..a4bb5dc06 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -228,6 +228,9 @@ private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, Wo if(targetProperty!=null) { targetProperty = Expression.Property(targetProperty, propertyName); + }else + { + break; } } From adc90cbbd12427eee379117ea474e5733580d405 Mon Sep 17 00:00:00 2001 From: Wangyang Ding Date: Wed, 26 May 2021 17:37:23 +0800 Subject: [PATCH 130/342] add indexed properties support --- WorkflowCore.sln | 9 ++- .../Services/DefinitionLoader.cs | 67 ++++++++++++++++--- .../DictionaryData.yml | 10 +++ .../HelloWorld.yml | 24 +++++++ .../MyDataClass.cs | 21 ++++++ .../Steps/HelloWorld.cs | 17 +++++ .../WorkflowCore.Tests.YmalDefinition.csproj | 45 +++++++++++++ .../YmalDefinitionTest.cs | 46 +++++++++++++ 8 files changed, 230 insertions(+), 9 deletions(-) create mode 100644 test/WorkflowCore.Tests.YmalDefinition/DictionaryData.yml create mode 100644 test/WorkflowCore.Tests.YmalDefinition/HelloWorld.yml create mode 100644 test/WorkflowCore.Tests.YmalDefinition/MyDataClass.cs create mode 100644 test/WorkflowCore.Tests.YmalDefinition/Steps/HelloWorld.cs create mode 100644 test/WorkflowCore.Tests.YmalDefinition/WorkflowCore.Tests.YmalDefinition.csproj create mode 100644 test/WorkflowCore.Tests.YmalDefinition/YmalDefinitionTest.cs diff --git a/WorkflowCore.sln b/WorkflowCore.sln index be18fd721..b80b2e757 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -150,7 +150,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Tests.QueuePro EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample19", "src\samples\WorkflowCore.Sample19\WorkflowCore.Sample19.csproj", "{1223ED47-3E5E-4960-B70D-DFAF550F6666}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Persistence.RavenDB", "src\providers\WorkflowCore.Persistence.RavenDB\WorkflowCore.Persistence.RavenDB.csproj", "{AF205715-C8B7-42EF-BF14-AFC9E7F27242}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Persistence.RavenDB", "src\providers\WorkflowCore.Persistence.RavenDB\WorkflowCore.Persistence.RavenDB.csproj", "{AF205715-C8B7-42EF-BF14-AFC9E7F27242}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Tests.YmalDefinition", "test\WorkflowCore.Tests.YmalDefinition\WorkflowCore.Tests.YmalDefinition.csproj", "{099259BB-ABCD-4C7C-AFAE-56A2730B9309}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -374,6 +376,10 @@ Global {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Debug|Any CPU.Build.0 = Debug|Any CPU {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Release|Any CPU.ActiveCfg = Release|Any CPU {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Release|Any CPU.Build.0 = Release|Any CPU + {099259BB-ABCD-4C7C-AFAE-56A2730B9309}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {099259BB-ABCD-4C7C-AFAE-56A2730B9309}.Debug|Any CPU.Build.0 = Debug|Any CPU + {099259BB-ABCD-4C7C-AFAE-56A2730B9309}.Release|Any CPU.ActiveCfg = Release|Any CPU + {099259BB-ABCD-4C7C-AFAE-56A2730B9309}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -436,6 +442,7 @@ Global {54DE20BA-EBA7-4BF0-9BD9-F03766849716} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} {1223ED47-3E5E-4960-B70D-DFAF550F6666} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} {AF205715-C8B7-42EF-BF14-AFC9E7F27242} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} + {099259BB-ABCD-4C7C-AFAE-56A2730B9309} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC0FA8D3-6449-4FDA-BB46-ECF58FAD23B4} diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index a4bb5dc06..23546b99a 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -223,23 +223,74 @@ private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, Wo PropertyInfo propertyInfo = null; String[] paths = output.Key.Split('.'); - foreach(String propertyName in paths) + + bool hasAddOutput = false; + + foreach (String propertyName in paths) { - if(targetProperty!=null) + if (hasAddOutput) { - targetProperty = Expression.Property(targetProperty, propertyName); - }else + throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}"); + } + + if (targetProperty == null) { break; + } + + if (propertyName.Contains("[")) + { + String[] items = propertyName.Split('['); + + if (items.Length != 2) + { + throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}"); + } + + items[1] = items[1].Trim().TrimEnd(']').Trim().Trim('"'); + + MemberExpression memberExpression = Expression.Property(targetProperty, items[0]); + + if (memberExpression == null) + { + throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}"); + } + propertyInfo = (PropertyInfo)memberExpression.Member; + var propertyType = propertyInfo.PropertyType.GetProperty("Item"); + + propertyInfo = propertyInfo.PropertyType.GetProperty("Item"); + + Action acn = (pStep, pData) => + { + var targetExpr = Expression.Lambda(memberExpression, dataParameter); + object data = targetExpr.Compile().DynamicInvoke(pData); + object resolvedValue = sourceExpr.Compile().DynamicInvoke(pStep); ; + propertyInfo.SetValue(data, resolvedValue, new object[] { items[1] }); + }; + + step.Outputs.Add(new ActionParameter(acn)); + + hasAddOutput = true; + } + else + { + try + { + targetProperty = Expression.Property(targetProperty, propertyName); + }catch + { + targetProperty = null; + break; + } } } - - if (targetProperty != null) - { + + if (targetProperty != null && ! hasAddOutput) + { var targetExpr = Expression.Lambda(targetProperty, dataParameter); step.Outputs.Add(new MemberMapParameter(sourceExpr, targetExpr)); } - else + else if (! hasAddOutput) { // If we did not find a matching property try to find a Indexer with string parameter propertyInfo = dataType.GetProperty("Item"); diff --git a/test/WorkflowCore.Tests.YmalDefinition/DictionaryData.yml b/test/WorkflowCore.Tests.YmalDefinition/DictionaryData.yml new file mode 100644 index 000000000..9e8771448 --- /dev/null +++ b/test/WorkflowCore.Tests.YmalDefinition/DictionaryData.yml @@ -0,0 +1,10 @@ +Id: DictionaryData +Version: 1 +DataType: System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.Int32, System.Private.CoreLib]], System.Private.CoreLib +Steps: +- Id: HelloWorld1 + Name: HelloWorld1 + StepType: WorkflowCore.Tests.YmalDefinition.Steps.HelloWorld, WorkflowCore.Tests.YmalDefinition + Outputs: + Value1: 10 + Value2: 11 \ No newline at end of file diff --git a/test/WorkflowCore.Tests.YmalDefinition/HelloWorld.yml b/test/WorkflowCore.Tests.YmalDefinition/HelloWorld.yml new file mode 100644 index 000000000..1ad77d12e --- /dev/null +++ b/test/WorkflowCore.Tests.YmalDefinition/HelloWorld.yml @@ -0,0 +1,24 @@ +Id: HelloWorld +Version: 1 +DataType: WorkflowCore.Tests.YmalDefinition.MyDataClass, WorkflowCore.Tests.YmalDefinition +Steps: +- Id: HelloWorld1 + Name: HelloWorld1 + StepType: WorkflowCore.Tests.YmalDefinition.Steps.HelloWorld, WorkflowCore.Tests.YmalDefinition + Outputs: + anotherData.Value3: 100121 + Value1: 10 + Value2: 11 + NextStepId: HelloWorld2 +- Id: HelloWorld2 + Name: HelloWorld2 + StepType: WorkflowCore.Tests.YmalDefinition.Steps.HelloWorld, WorkflowCore.Tests.YmalDefinition + Inputs: + Value: data.anotherData.Value3 + Outputs: + Dict["testKey1"]: 100 + Dict["testKey"]: 101 + NextStepId: HelloWorld3 +- Id: HelloWorld3 + Name: HelloWorld3 + StepType: WorkflowCore.Tests.YmalDefinition.Steps.HelloWorld, WorkflowCore.Tests.YmalDefinition diff --git a/test/WorkflowCore.Tests.YmalDefinition/MyDataClass.cs b/test/WorkflowCore.Tests.YmalDefinition/MyDataClass.cs new file mode 100644 index 000000000..fc78e0c3b --- /dev/null +++ b/test/WorkflowCore.Tests.YmalDefinition/MyDataClass.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace WorkflowCore.Tests.YmalDefinition +{ + public class MyDataClass + { + public int Value1 { get; set; } + + public int Value2 { get; set; } + + public Dictionary Dict { get; set; } + + public AnotherDataClass anotherData { get; set; } + } + public class AnotherDataClass + { + public int Value3 { get; set; } + } +} diff --git a/test/WorkflowCore.Tests.YmalDefinition/Steps/HelloWorld.cs b/test/WorkflowCore.Tests.YmalDefinition/Steps/HelloWorld.cs new file mode 100644 index 000000000..9b522e6f0 --- /dev/null +++ b/test/WorkflowCore.Tests.YmalDefinition/Steps/HelloWorld.cs @@ -0,0 +1,17 @@ +using System; +using System.Linq; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Tests.YmalDefinition.Steps +{ + public class HelloWorld : StepBody + { + public int Value { get; set; } = 10; + public override ExecutionResult Run(IStepExecutionContext context) + { + Console.WriteLine("Value is " + Value); + return ExecutionResult.Next(); + } + } +} diff --git a/test/WorkflowCore.Tests.YmalDefinition/WorkflowCore.Tests.YmalDefinition.csproj b/test/WorkflowCore.Tests.YmalDefinition/WorkflowCore.Tests.YmalDefinition.csproj new file mode 100644 index 000000000..f948eb349 --- /dev/null +++ b/test/WorkflowCore.Tests.YmalDefinition/WorkflowCore.Tests.YmalDefinition.csproj @@ -0,0 +1,45 @@ + + + + netcoreapp3.1 + + false + + + + + + + + + + + + + + + + + + + HelloWorld.yml + True + True + + + True + True + HelloWorld.yml + + + + + + Always + + + Always + + + + diff --git a/test/WorkflowCore.Tests.YmalDefinition/YmalDefinitionTest.cs b/test/WorkflowCore.Tests.YmalDefinition/YmalDefinitionTest.cs new file mode 100644 index 000000000..8b5533492 --- /dev/null +++ b/test/WorkflowCore.Tests.YmalDefinition/YmalDefinitionTest.cs @@ -0,0 +1,46 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using WorkflowCore.Interface; +using WorkflowCore.Testing; +using Xunit; + +namespace WorkflowCore.Tests.YmalDefinition +{ + public class YmalDefinitionTest:YamlWorkflowTest + { + + [Fact] + public void LoadWorkflowDefinitions_NoException() + { + Setup(); + + MyDataClass myData = new MyDataClass() { + Value1 = 1, + Value2 = 2, + Dict = new Dictionary(), + anotherData = new AnotherDataClass() { Value3 = 3 } + }; + myData.Dict["testKey"] = 5; + + String workflowInstanceId=StartWorkflow(File.ReadAllText("HelloWorld.yml"), myData); + WaitForWorkflowToComplete(workflowInstanceId, TimeSpan.FromSeconds(30)); + MyDataClass resultData = GetData(workflowInstanceId); + Assert.Equal(10, resultData.Value1); + Assert.Equal(11, resultData.Value2); + Assert.Equal(100121, resultData.anotherData.Value3); + Assert.Equal(100, resultData.Dict["testKey1"]); + Assert.Equal(101, resultData.Dict["testKey"]); + + workflowInstanceId = StartWorkflow(File.ReadAllText("DictionaryData.yml"), new Dictionary()); + WaitForWorkflowToComplete(workflowInstanceId, TimeSpan.FromSeconds(30)); + Dictionary resultData2 = GetData>(workflowInstanceId); + Assert.Equal(10, resultData2["Value1"]); + Assert.Equal(11, resultData2["Value2"]); + } + } +} From 3679769fc7f374e43f4a42783ce339d4c19a0f9a Mon Sep 17 00:00:00 2001 From: Wangyang Ding Date: Wed, 26 May 2021 17:41:44 +0800 Subject: [PATCH 131/342] add indexed properties support --- src/WorkflowCore.DSL/Services/DefinitionLoader.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index 23546b99a..ca50cffd8 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -255,10 +255,7 @@ private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, Wo { throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}"); } - propertyInfo = (PropertyInfo)memberExpression.Member; - var propertyType = propertyInfo.PropertyType.GetProperty("Item"); - - propertyInfo = propertyInfo.PropertyType.GetProperty("Item"); + propertyInfo = ((PropertyInfo)memberExpression.Member).PropertyType.GetProperty("Item"); Action acn = (pStep, pData) => { @@ -269,7 +266,6 @@ private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, Wo }; step.Outputs.Add(new ActionParameter(acn)); - hasAddOutput = true; } else From d4d2d5645fc499c9f9be86469505efbba6c56cb4 Mon Sep 17 00:00:00 2001 From: Wangyang Ding Date: Thu, 27 May 2021 13:21:37 +0800 Subject: [PATCH 132/342] update unit test --- .../DataTypes/CounterBoardWithDynamicData.cs | 9 +++ test/WorkflowCore.TestAssets/Utils.cs | 4 ++ .../WorkflowCore.TestAssets.csproj | 4 ++ .../stored-dynamic-definition.yaml | 58 +++++++++++++++++++ .../DefinitionLoaderTests.cs | 10 ++++ 5 files changed, 85 insertions(+) create mode 100644 test/WorkflowCore.TestAssets/DataTypes/CounterBoardWithDynamicData.cs create mode 100644 test/WorkflowCore.TestAssets/stored-dynamic-definition.yaml diff --git a/test/WorkflowCore.TestAssets/DataTypes/CounterBoardWithDynamicData.cs b/test/WorkflowCore.TestAssets/DataTypes/CounterBoardWithDynamicData.cs new file mode 100644 index 000000000..49875ba41 --- /dev/null +++ b/test/WorkflowCore.TestAssets/DataTypes/CounterBoardWithDynamicData.cs @@ -0,0 +1,9 @@ +using System; + +namespace WorkflowCore.TestAssets.DataTypes +{ + public class CounterBoardWithDynamicData: CounterBoard + { + public DynamicData DynamicDataInstance { get; set; } + } +} diff --git a/test/WorkflowCore.TestAssets/Utils.cs b/test/WorkflowCore.TestAssets/Utils.cs index 723cca992..b7a7919cd 100644 --- a/test/WorkflowCore.TestAssets/Utils.cs +++ b/test/WorkflowCore.TestAssets/Utils.cs @@ -30,6 +30,10 @@ public static string GetTestDefinitionDynamicJson() { return File.ReadAllText("stored-dynamic-definition.json"); } + public static string GetTestDefinitionDynamicYaml() + { + return File.ReadAllText("stored-dynamic-definition.yaml"); + } public static string GetTestDefinitionJsonMissingInputProperty() { diff --git a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj index 12da1f57b..0ff0a1fc2 100644 --- a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj +++ b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj @@ -13,9 +13,13 @@ + + + Always + Always diff --git a/test/WorkflowCore.TestAssets/stored-dynamic-definition.yaml b/test/WorkflowCore.TestAssets/stored-dynamic-definition.yaml new file mode 100644 index 000000000..b14313366 --- /dev/null +++ b/test/WorkflowCore.TestAssets/stored-dynamic-definition.yaml @@ -0,0 +1,58 @@ +Id: Test +Version: 1 +DataType: WorkflowCore.TestAssets.DataTypes.CounterBoardWithDynamicData, WorkflowCore.TestAssets +Steps: +- Id: Step1 + StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets + ErrorBehavior: Retry + Inputs: + Value: data.DynamicDataInstance["test"] + Outputs: + DynamicDataInstance["test"]: step.Value + NextStepId: Step2 +- Id: Step2 + StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets + Inputs: + Value: data.Counter2 + Outputs: + Counter2: step.Value + NextStepId: Step3 +- Id: Step3 + StepType: WorkflowCore.Primitives.If, WorkflowCore + NextStepId: Step4 + Inputs: + Condition: object.Equals(data.Flag1, true) + Do: + - - Id: Step3.1.1 + StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets + Inputs: + Value: data.Counter3 + Outputs: + Counter3: step.Value + NextStepId: Step3.1.2 + - Id: Step3.1.2 + StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets + Inputs: + Value: data.Counter4 + Outputs: + Counter4: step.Value + - - Id: Step3.2.1 + StepType: WorkflowCore.Primitives.WaitFor, WorkflowCore + NextStepId: Step3.2.2 + CancelCondition: data.Flag2 + Inputs: + EventName: '"Event1"' + EventKey: '"Key1"' + EffectiveDate: DateTime.Now + - Id: Step3.2.2 + StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets + Inputs: + Value: data.Counter5 + Outputs: + Counter5: step.Value +- Id: Step4 + StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets + Inputs: + Value: data.Counter6 + Outputs: + Counter6: step.Value diff --git a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs index 6176b6ee6..01a743e8a 100644 --- a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs +++ b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs @@ -43,6 +43,16 @@ public void ParseDefinition() A.CallTo(() => _registry.RegisterWorkflow(A.That.Matches(MatchTestDefinition, ""))).MustHaveHappened(); } + [Fact(DisplayName = "Should parse definition")] + public void ParseDefinitionPropertyDynamic() + { + _subject.LoadDefinition(TestAssets.Utils.GetTestDefinitionDynamicYaml(), Deserializers.Yaml); + + A.CallTo(() => _registry.RegisterWorkflow(A.That.Matches(x => x.Id == "Test"))).MustHaveHappened(); + A.CallTo(() => _registry.RegisterWorkflow(A.That.Matches(x => x.Version == 1))).MustHaveHappened(); + A.CallTo(() => _registry.RegisterWorkflow(A.That.Matches(x => x.DataType == typeof(CounterBoardWithDynamicData)))).MustHaveHappened(); + A.CallTo(() => _registry.RegisterWorkflow(A.That.Matches(MatchTestDefinition, ""))).MustHaveHappened(); + } [Fact(DisplayName = "Should parse definition")] public void ParseDefinitionDynamic() From 5fd8b17c3c63d7a02167d840908443e8b30f862f Mon Sep 17 00:00:00 2001 From: Wangyang Ding Date: Thu, 27 May 2021 13:24:34 +0800 Subject: [PATCH 133/342] update unit test --- WorkflowCore.sln | 7 ------- 1 file changed, 7 deletions(-) diff --git a/WorkflowCore.sln b/WorkflowCore.sln index b80b2e757..de509ed05 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -152,8 +152,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample19", "sr EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Persistence.RavenDB", "src\providers\WorkflowCore.Persistence.RavenDB\WorkflowCore.Persistence.RavenDB.csproj", "{AF205715-C8B7-42EF-BF14-AFC9E7F27242}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Tests.YmalDefinition", "test\WorkflowCore.Tests.YmalDefinition\WorkflowCore.Tests.YmalDefinition.csproj", "{099259BB-ABCD-4C7C-AFAE-56A2730B9309}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -376,10 +374,6 @@ Global {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Debug|Any CPU.Build.0 = Debug|Any CPU {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Release|Any CPU.ActiveCfg = Release|Any CPU {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Release|Any CPU.Build.0 = Release|Any CPU - {099259BB-ABCD-4C7C-AFAE-56A2730B9309}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {099259BB-ABCD-4C7C-AFAE-56A2730B9309}.Debug|Any CPU.Build.0 = Debug|Any CPU - {099259BB-ABCD-4C7C-AFAE-56A2730B9309}.Release|Any CPU.ActiveCfg = Release|Any CPU - {099259BB-ABCD-4C7C-AFAE-56A2730B9309}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -442,7 +436,6 @@ Global {54DE20BA-EBA7-4BF0-9BD9-F03766849716} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} {1223ED47-3E5E-4960-B70D-DFAF550F6666} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} {AF205715-C8B7-42EF-BF14-AFC9E7F27242} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} - {099259BB-ABCD-4C7C-AFAE-56A2730B9309} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC0FA8D3-6449-4FDA-BB46-ECF58FAD23B4} From a84673ef0bf71f86395a909754116922df9bfcb9 Mon Sep 17 00:00:00 2001 From: Wangyang Ding Date: Thu, 27 May 2021 13:26:26 +0800 Subject: [PATCH 134/342] update unit test --- .../DictionaryData.yml | 10 ---- .../HelloWorld.yml | 24 ---------- .../MyDataClass.cs | 21 --------- .../Steps/HelloWorld.cs | 17 ------- .../WorkflowCore.Tests.YmalDefinition.csproj | 45 ------------------ .../YmalDefinitionTest.cs | 46 ------------------- 6 files changed, 163 deletions(-) delete mode 100644 test/WorkflowCore.Tests.YmalDefinition/DictionaryData.yml delete mode 100644 test/WorkflowCore.Tests.YmalDefinition/HelloWorld.yml delete mode 100644 test/WorkflowCore.Tests.YmalDefinition/MyDataClass.cs delete mode 100644 test/WorkflowCore.Tests.YmalDefinition/Steps/HelloWorld.cs delete mode 100644 test/WorkflowCore.Tests.YmalDefinition/WorkflowCore.Tests.YmalDefinition.csproj delete mode 100644 test/WorkflowCore.Tests.YmalDefinition/YmalDefinitionTest.cs diff --git a/test/WorkflowCore.Tests.YmalDefinition/DictionaryData.yml b/test/WorkflowCore.Tests.YmalDefinition/DictionaryData.yml deleted file mode 100644 index 9e8771448..000000000 --- a/test/WorkflowCore.Tests.YmalDefinition/DictionaryData.yml +++ /dev/null @@ -1,10 +0,0 @@ -Id: DictionaryData -Version: 1 -DataType: System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.Int32, System.Private.CoreLib]], System.Private.CoreLib -Steps: -- Id: HelloWorld1 - Name: HelloWorld1 - StepType: WorkflowCore.Tests.YmalDefinition.Steps.HelloWorld, WorkflowCore.Tests.YmalDefinition - Outputs: - Value1: 10 - Value2: 11 \ No newline at end of file diff --git a/test/WorkflowCore.Tests.YmalDefinition/HelloWorld.yml b/test/WorkflowCore.Tests.YmalDefinition/HelloWorld.yml deleted file mode 100644 index 1ad77d12e..000000000 --- a/test/WorkflowCore.Tests.YmalDefinition/HelloWorld.yml +++ /dev/null @@ -1,24 +0,0 @@ -Id: HelloWorld -Version: 1 -DataType: WorkflowCore.Tests.YmalDefinition.MyDataClass, WorkflowCore.Tests.YmalDefinition -Steps: -- Id: HelloWorld1 - Name: HelloWorld1 - StepType: WorkflowCore.Tests.YmalDefinition.Steps.HelloWorld, WorkflowCore.Tests.YmalDefinition - Outputs: - anotherData.Value3: 100121 - Value1: 10 - Value2: 11 - NextStepId: HelloWorld2 -- Id: HelloWorld2 - Name: HelloWorld2 - StepType: WorkflowCore.Tests.YmalDefinition.Steps.HelloWorld, WorkflowCore.Tests.YmalDefinition - Inputs: - Value: data.anotherData.Value3 - Outputs: - Dict["testKey1"]: 100 - Dict["testKey"]: 101 - NextStepId: HelloWorld3 -- Id: HelloWorld3 - Name: HelloWorld3 - StepType: WorkflowCore.Tests.YmalDefinition.Steps.HelloWorld, WorkflowCore.Tests.YmalDefinition diff --git a/test/WorkflowCore.Tests.YmalDefinition/MyDataClass.cs b/test/WorkflowCore.Tests.YmalDefinition/MyDataClass.cs deleted file mode 100644 index fc78e0c3b..000000000 --- a/test/WorkflowCore.Tests.YmalDefinition/MyDataClass.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace WorkflowCore.Tests.YmalDefinition -{ - public class MyDataClass - { - public int Value1 { get; set; } - - public int Value2 { get; set; } - - public Dictionary Dict { get; set; } - - public AnotherDataClass anotherData { get; set; } - } - public class AnotherDataClass - { - public int Value3 { get; set; } - } -} diff --git a/test/WorkflowCore.Tests.YmalDefinition/Steps/HelloWorld.cs b/test/WorkflowCore.Tests.YmalDefinition/Steps/HelloWorld.cs deleted file mode 100644 index 9b522e6f0..000000000 --- a/test/WorkflowCore.Tests.YmalDefinition/Steps/HelloWorld.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Linq; -using WorkflowCore.Interface; -using WorkflowCore.Models; - -namespace WorkflowCore.Tests.YmalDefinition.Steps -{ - public class HelloWorld : StepBody - { - public int Value { get; set; } = 10; - public override ExecutionResult Run(IStepExecutionContext context) - { - Console.WriteLine("Value is " + Value); - return ExecutionResult.Next(); - } - } -} diff --git a/test/WorkflowCore.Tests.YmalDefinition/WorkflowCore.Tests.YmalDefinition.csproj b/test/WorkflowCore.Tests.YmalDefinition/WorkflowCore.Tests.YmalDefinition.csproj deleted file mode 100644 index f948eb349..000000000 --- a/test/WorkflowCore.Tests.YmalDefinition/WorkflowCore.Tests.YmalDefinition.csproj +++ /dev/null @@ -1,45 +0,0 @@ - - - - netcoreapp3.1 - - false - - - - - - - - - - - - - - - - - - - HelloWorld.yml - True - True - - - True - True - HelloWorld.yml - - - - - - Always - - - Always - - - - diff --git a/test/WorkflowCore.Tests.YmalDefinition/YmalDefinitionTest.cs b/test/WorkflowCore.Tests.YmalDefinition/YmalDefinitionTest.cs deleted file mode 100644 index 8b5533492..000000000 --- a/test/WorkflowCore.Tests.YmalDefinition/YmalDefinitionTest.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Linq.Expressions; -using System.Threading; -using WorkflowCore.Interface; -using WorkflowCore.Testing; -using Xunit; - -namespace WorkflowCore.Tests.YmalDefinition -{ - public class YmalDefinitionTest:YamlWorkflowTest - { - - [Fact] - public void LoadWorkflowDefinitions_NoException() - { - Setup(); - - MyDataClass myData = new MyDataClass() { - Value1 = 1, - Value2 = 2, - Dict = new Dictionary(), - anotherData = new AnotherDataClass() { Value3 = 3 } - }; - myData.Dict["testKey"] = 5; - - String workflowInstanceId=StartWorkflow(File.ReadAllText("HelloWorld.yml"), myData); - WaitForWorkflowToComplete(workflowInstanceId, TimeSpan.FromSeconds(30)); - MyDataClass resultData = GetData(workflowInstanceId); - Assert.Equal(10, resultData.Value1); - Assert.Equal(11, resultData.Value2); - Assert.Equal(100121, resultData.anotherData.Value3); - Assert.Equal(100, resultData.Dict["testKey1"]); - Assert.Equal(101, resultData.Dict["testKey"]); - - workflowInstanceId = StartWorkflow(File.ReadAllText("DictionaryData.yml"), new Dictionary()); - WaitForWorkflowToComplete(workflowInstanceId, TimeSpan.FromSeconds(30)); - Dictionary resultData2 = GetData>(workflowInstanceId); - Assert.Equal(10, resultData2["Value1"]); - Assert.Equal(11, resultData2["Value2"]); - } - } -} From cab5eae459beabb70ac0ea184b8552092de2dcd3 Mon Sep 17 00:00:00 2001 From: Wangyang Ding Date: Mon, 31 May 2021 10:38:50 +0800 Subject: [PATCH 135/342] update --- .../Services/DefinitionLoader.cs | 147 +++++++++++------- .../DataTypes/CounterBoardWithDynamicData.cs | 1 + .../stored-dynamic-definition.yaml | 2 +- 3 files changed, 89 insertions(+), 61 deletions(-) diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index ca50cffd8..90b830990 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -217,90 +217,117 @@ private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, Wo var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { stepParameter }, typeof(object), output.Value); var dataParameter = Expression.Parameter(dataType, "data"); - Expression targetProperty = dataParameter; - // Check if our datatype has a matching property - PropertyInfo propertyInfo = null; - String[] paths = output.Key.Split('.'); - - bool hasAddOutput = false; - - foreach (String propertyName in paths) + if(output.Key.Contains(".") || output.Key.Contains("[")) { - if (hasAddOutput) - { - throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}"); - } + AttachNestedOutput(output, step, source, sourceExpr, dataParameter); + }else + { + AttachDirectlyOutput(output, step, dataType, sourceExpr, dataParameter); + } + } + } - if (targetProperty == null) - { - break; - } + private void AttachDirectlyOutput(KeyValuePair output, WorkflowStep step, Type dataType, LambdaExpression sourceExpr, ParameterExpression dataParameter) + { + Expression targetProperty; - if (propertyName.Contains("[")) - { - String[] items = propertyName.Split('['); + // Check if our datatype has a matching property + var propertyInfo = dataType.GetProperty(output.Key); + if (propertyInfo != null) + { + targetProperty = Expression.Property(dataParameter, propertyInfo); + var targetExpr = Expression.Lambda(targetProperty, dataParameter); + step.Outputs.Add(new MemberMapParameter(sourceExpr, targetExpr)); + } + else + { + // If we did not find a matching property try to find a Indexer with string parameter + propertyInfo = dataType.GetProperty("Item"); + targetProperty = Expression.Property(dataParameter, propertyInfo, Expression.Constant(output.Key)); - if (items.Length != 2) - { - throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}"); - } + Action acn = (pStep, pData) => + { + object resolvedValue = sourceExpr.Compile().DynamicInvoke(pStep); ; + propertyInfo.SetValue(pData, resolvedValue, new object[] { output.Key }); + }; - items[1] = items[1].Trim().TrimEnd(']').Trim().Trim('"'); + step.Outputs.Add(new ActionParameter(acn)); + } - MemberExpression memberExpression = Expression.Property(targetProperty, items[0]); + } - if (memberExpression == null) - { - throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}"); - } - propertyInfo = ((PropertyInfo)memberExpression.Member).PropertyType.GetProperty("Item"); + private void AttachNestedOutput( KeyValuePair output, WorkflowStep step, StepSourceV1 source, LambdaExpression sourceExpr, ParameterExpression dataParameter) + { + PropertyInfo propertyInfo = null; + String[] paths = output.Key.Split('.'); + + Expression targetProperty = dataParameter; - Action acn = (pStep, pData) => - { - var targetExpr = Expression.Lambda(memberExpression, dataParameter); - object data = targetExpr.Compile().DynamicInvoke(pData); - object resolvedValue = sourceExpr.Compile().DynamicInvoke(pStep); ; - propertyInfo.SetValue(data, resolvedValue, new object[] { items[1] }); - }; - - step.Outputs.Add(new ActionParameter(acn)); - hasAddOutput = true; - } - else - { - try - { - targetProperty = Expression.Property(targetProperty, propertyName); - }catch - { - targetProperty = null; - break; - } - } + bool hasAddOutput = false; + + foreach (String propertyName in paths) + { + if (hasAddOutput) + { + throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}"); } - if (targetProperty != null && ! hasAddOutput) + if (targetProperty == null) { - var targetExpr = Expression.Lambda(targetProperty, dataParameter); - step.Outputs.Add(new MemberMapParameter(sourceExpr, targetExpr)); + break; } - else if (! hasAddOutput) + + if (propertyName.Contains("[")) { - // If we did not find a matching property try to find a Indexer with string parameter - propertyInfo = dataType.GetProperty("Item"); - targetProperty = Expression.Property(dataParameter, propertyInfo, Expression.Constant(output.Key)); + String[] items = propertyName.Split('['); + + if (items.Length != 2) + { + throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}"); + } + + items[1] = items[1].Trim().TrimEnd(']').Trim().Trim('"'); + + MemberExpression memberExpression = Expression.Property(targetProperty, items[0]); + + if (memberExpression == null) + { + throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}"); + } + propertyInfo = ((PropertyInfo)memberExpression.Member).PropertyType.GetProperty("Item"); Action acn = (pStep, pData) => { + var targetExpr = Expression.Lambda(memberExpression, dataParameter); + object data = targetExpr.Compile().DynamicInvoke(pData); object resolvedValue = sourceExpr.Compile().DynamicInvoke(pStep); ; - propertyInfo.SetValue(pData, resolvedValue, new object[] { output.Key }); + propertyInfo.SetValue(data, resolvedValue, new object[] { items[1] }); }; step.Outputs.Add(new ActionParameter(acn)); + hasAddOutput = true; + } + else + { + try + { + targetProperty = Expression.Property(targetProperty, propertyName); + } + catch + { + targetProperty = null; + break; + } } } + + if (targetProperty != null && !hasAddOutput) + { + var targetExpr = Expression.Lambda(targetProperty, dataParameter); + step.Outputs.Add(new MemberMapParameter(sourceExpr, targetExpr)); + } } private void AttachOutcomes(StepSourceV1 source, Type dataType, WorkflowStep step) diff --git a/test/WorkflowCore.TestAssets/DataTypes/CounterBoardWithDynamicData.cs b/test/WorkflowCore.TestAssets/DataTypes/CounterBoardWithDynamicData.cs index 49875ba41..3a708724d 100644 --- a/test/WorkflowCore.TestAssets/DataTypes/CounterBoardWithDynamicData.cs +++ b/test/WorkflowCore.TestAssets/DataTypes/CounterBoardWithDynamicData.cs @@ -5,5 +5,6 @@ namespace WorkflowCore.TestAssets.DataTypes public class CounterBoardWithDynamicData: CounterBoard { public DynamicData DynamicDataInstance { get; set; } + public CounterBoard CounterBoardInstance { get; set; } } } diff --git a/test/WorkflowCore.TestAssets/stored-dynamic-definition.yaml b/test/WorkflowCore.TestAssets/stored-dynamic-definition.yaml index b14313366..6c38cd67f 100644 --- a/test/WorkflowCore.TestAssets/stored-dynamic-definition.yaml +++ b/test/WorkflowCore.TestAssets/stored-dynamic-definition.yaml @@ -15,7 +15,7 @@ Steps: Inputs: Value: data.Counter2 Outputs: - Counter2: step.Value + CounterBoardInstance.Counter1: step.Value NextStepId: Step3 - Id: Step3 StepType: WorkflowCore.Primitives.If, WorkflowCore From 2d1962c82313e32646607ef7827ee62df414623f Mon Sep 17 00:00:00 2001 From: lyzerk Date: Tue, 1 Jun 2021 12:31:10 +0300 Subject: [PATCH 136/342] ActivityName as expression. It solves #542 issue. --- WorkflowCore.sln | 7 ++ .../Interface/IWorkflowModifier.cs | 10 +++ .../Services/FluentBuilders/StepBuilder.cs | 19 +++++ .../FluentBuilders/WorkflowBuilder.cs | 4 + .../WorkflowCore.Sample20/ActivityWorkflow.cs | 29 +++++++ src/samples/WorkflowCore.Sample20/Program.cs | 53 +++++++++++++ src/samples/WorkflowCore.Sample20/README.md | 34 +++++++++ .../Steps/CustomMessage.cs | 19 +++++ .../Steps/GoodbyeWorld.cs | 16 ++++ .../WorkflowCore.Sample20/Steps/HelloWorld.cs | 16 ++++ .../WorkflowCore.Sample20.csproj | 20 +++++ .../Scenarios/ActivityScenario2.cs | 75 +++++++++++++++++++ 12 files changed, 302 insertions(+) create mode 100644 src/samples/WorkflowCore.Sample20/ActivityWorkflow.cs create mode 100644 src/samples/WorkflowCore.Sample20/Program.cs create mode 100644 src/samples/WorkflowCore.Sample20/README.md create mode 100644 src/samples/WorkflowCore.Sample20/Steps/CustomMessage.cs create mode 100644 src/samples/WorkflowCore.Sample20/Steps/GoodbyeWorld.cs create mode 100644 src/samples/WorkflowCore.Sample20/Steps/HelloWorld.cs create mode 100644 src/samples/WorkflowCore.Sample20/WorkflowCore.Sample20.csproj create mode 100644 test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario2.cs diff --git a/WorkflowCore.sln b/WorkflowCore.sln index be18fd721..8bd5d6ca1 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -152,6 +152,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample19", "sr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Persistence.RavenDB", "src\providers\WorkflowCore.Persistence.RavenDB\WorkflowCore.Persistence.RavenDB.csproj", "{AF205715-C8B7-42EF-BF14-AFC9E7F27242}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample20", "src\samples\WorkflowCore.Sample20\WorkflowCore.Sample20.csproj", "{68D1B955-1049-477B-A894-13FCB96C45DE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -374,6 +376,10 @@ Global {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Debug|Any CPU.Build.0 = Debug|Any CPU {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Release|Any CPU.ActiveCfg = Release|Any CPU {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Release|Any CPU.Build.0 = Release|Any CPU + {68D1B955-1049-477B-A894-13FCB96C45DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {68D1B955-1049-477B-A894-13FCB96C45DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {68D1B955-1049-477B-A894-13FCB96C45DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {68D1B955-1049-477B-A894-13FCB96C45DE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -436,6 +442,7 @@ Global {54DE20BA-EBA7-4BF0-9BD9-F03766849716} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} {1223ED47-3E5E-4960-B70D-DFAF550F6666} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} {AF205715-C8B7-42EF-BF14-AFC9E7F27242} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} + {68D1B955-1049-477B-A894-13FCB96C45DE} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC0FA8D3-6449-4FDA-BB46-ECF58FAD23B4} diff --git a/src/WorkflowCore/Interface/IWorkflowModifier.cs b/src/WorkflowCore/Interface/IWorkflowModifier.cs index d8af82616..1ecd093d0 100644 --- a/src/WorkflowCore/Interface/IWorkflowModifier.cs +++ b/src/WorkflowCore/Interface/IWorkflowModifier.cs @@ -152,5 +152,15 @@ IContainerStepBuilder Recur(Expression Activity(string activityName, Expression> parameters = null, Expression> effectiveDate = null, Expression> cancelCondition = null); + /// + /// Wait here until an external activity is complete + /// + /// The name used to identify the activity to wait for + /// The data to pass the external activity worker + /// Listen for events as of this effective date + /// A conditon that when true will cancel this WaitFor + /// + IStepBuilder Activity(Expression> activityName, Expression> parameters = null, + Expression> effectiveDate = null, Expression> cancelCondition = null); } } \ No newline at end of file diff --git a/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs b/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs index f5d25730a..9cfeae852 100644 --- a/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs +++ b/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs @@ -522,5 +522,24 @@ public IStepBuilder Activity(string activityName, Expression Activity(Expression> activityName, Expression> parameters = null, Expression> effectiveDate = null, Expression> cancelCondition = null) + { + var newStep = new WorkflowStep(); + newStep.CancelCondition = cancelCondition; + + WorkflowBuilder.AddStep(newStep); + var stepBuilder = new StepBuilder(WorkflowBuilder, newStep); + stepBuilder.Input((step) => step.ActivityName, activityName); + + if (parameters != null) + stepBuilder.Input((step) => step.Parameters, parameters); + + if (effectiveDate != null) + stepBuilder.Input((step) => step.EffectiveDate, effectiveDate); + + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); + return stepBuilder; + } } } diff --git a/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs b/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs index 98788fa0c..f9d55f77e 100644 --- a/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs +++ b/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs @@ -271,6 +271,10 @@ public IStepBuilder Activity(string activityName, Expression Activity(Expression> activityName, Expression> parameters = null, Expression> effectiveDate = null, Expression> cancelCondition = null) + { + return Start().Activity(activityName, parameters, effectiveDate, cancelCondition); + } private IStepBuilder Start() { diff --git a/src/samples/WorkflowCore.Sample20/ActivityWorkflow.cs b/src/samples/WorkflowCore.Sample20/ActivityWorkflow.cs new file mode 100644 index 000000000..03208dcfd --- /dev/null +++ b/src/samples/WorkflowCore.Sample20/ActivityWorkflow.cs @@ -0,0 +1,29 @@ +using System; +using WorkflowCore.Interface; +using WorkflowCore.Sample20.Steps; + +namespace WorkflowCore.Sample20 +{ + class ActivityWorkflow : IWorkflow + { + public string Id => "activity-sample"; + public int Version => 1; + + public void Build(IWorkflowBuilder builder) + { + builder + .StartWith() + .Activity((data, context) => "get-approval-" + context.Workflow.Id, (data) => data.Request) + .Output(data => data.ApprovedBy, step => step.Result) + .Then() + .Input(step => step.Message, data => "Approved by " + data.ApprovedBy) + .Then(); + } + } + + class MyData + { + public string Request { get; set; } + public string ApprovedBy { get; set; } + } +} diff --git a/src/samples/WorkflowCore.Sample20/Program.cs b/src/samples/WorkflowCore.Sample20/Program.cs new file mode 100644 index 000000000..69009fe98 --- /dev/null +++ b/src/samples/WorkflowCore.Sample20/Program.cs @@ -0,0 +1,53 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System; +using WorkflowCore.Interface; + +namespace WorkflowCore.Sample20 +{ + class Program + { + static void Main(string[] args) + { + var serviceProvider = ConfigureServices(); + + //start the workflow host + var host = serviceProvider.GetService(); + host.RegisterWorkflow(); + host.Start(); + + Console.WriteLine("Starting workflow..."); + + var workflowId = host.StartWorkflow("activity-sample", new MyData { Request = "Spend $1,000,000" }).Result; + + var approval = host.GetPendingActivity("get-approval-" + workflowId, "worker1", TimeSpan.FromMinutes(1)).Result; + + if (approval != null) + { + Console.WriteLine("Approval required for " + approval.Parameters); + host.SubmitActivitySuccess(approval.Token, "John Smith"); + } + + Console.ReadLine(); + host.Stop(); + } + + private static IServiceProvider ConfigureServices() + { + //setup dependency injection + IServiceCollection services = new ServiceCollection(); + //services.AddWorkflow(); + services.AddWorkflow(x => x.UseMongoDB(@"mongodb://localhost:27017", "workflow")); + //services.AddWorkflow(x => x.UseSqlServer(@"Server=.;Database=WorkflowCore;Trusted_Connection=True;", true, true)); + //services.AddWorkflow(x => x.UsePostgreSQL(@"Server=127.0.0.1;Port=5432;Database=workflow;User Id=postgres;", true, true)); + services.AddLogging(cfg => + { + cfg.AddConsole(); + cfg.AddDebug(); + }); + + var serviceProvider = services.BuildServiceProvider(); + return serviceProvider; + } + } +} diff --git a/src/samples/WorkflowCore.Sample20/README.md b/src/samples/WorkflowCore.Sample20/README.md new file mode 100644 index 000000000..46f5d1e22 --- /dev/null +++ b/src/samples/WorkflowCore.Sample20/README.md @@ -0,0 +1,34 @@ +# Activity sample + +Illustrates how to have your workflow wait for an external activity that is fulfilled by a worker that you implement. + +This workflow will wait for the `get-approval-{workflowId}` activity and pass the request string to it as an input. + +The main reason behind of this example is Activities are global listeners. Therefore, in some cases, you want to be sure about its uniqueness. + +Also, you can take look the issue https://github.com/danielgerlag/workflow-core/issues/542 + +```c# +builder + .StartWith() + .Activity((data, context) => context.Workflow.Id, (data) => data.Request) + .Output(data => data.ApprovedBy, step => step.Result) + .Then() + .Input(step => step.Message, data => "Approved by " + data.ApprovedBy) + .Then(); +``` + +Then we implement an activity worker to pull pending activities of type `get-approval`, where we can inspect the input and submit a response back to the waiting workflow. + +```c# +var workflowId = host.StartWorkflow("activity-sample", new MyData { Request = "Spend $1,000,000" }).Result; + +var approval = host.GetPendingActivity("get-approval-" + workflowId, "worker1", TimeSpan.FromMinutes(1)).Result; + +if (approval != null) +{ + Console.WriteLine("Approval required for " + approval.Parameters); + host.SubmitActivitySuccess(approval.Token, "John Smith"); +} +``` + diff --git a/src/samples/WorkflowCore.Sample20/Steps/CustomMessage.cs b/src/samples/WorkflowCore.Sample20/Steps/CustomMessage.cs new file mode 100644 index 000000000..cad8eff61 --- /dev/null +++ b/src/samples/WorkflowCore.Sample20/Steps/CustomMessage.cs @@ -0,0 +1,19 @@ +using System; +using System.Linq; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Sample20.Steps +{ + public class CustomMessage : StepBody + { + + public string Message { get; set; } + + public override ExecutionResult Run(IStepExecutionContext context) + { + Console.WriteLine(Message); + return ExecutionResult.Next(); + } + } +} diff --git a/src/samples/WorkflowCore.Sample20/Steps/GoodbyeWorld.cs b/src/samples/WorkflowCore.Sample20/Steps/GoodbyeWorld.cs new file mode 100644 index 000000000..0908966d9 --- /dev/null +++ b/src/samples/WorkflowCore.Sample20/Steps/GoodbyeWorld.cs @@ -0,0 +1,16 @@ +using System; +using System.Linq; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Sample20.Steps +{ + public class GoodbyeWorld : StepBody + { + public override ExecutionResult Run(IStepExecutionContext context) + { + Console.WriteLine("Goodbye world"); + return ExecutionResult.Next(); + } + } +} diff --git a/src/samples/WorkflowCore.Sample20/Steps/HelloWorld.cs b/src/samples/WorkflowCore.Sample20/Steps/HelloWorld.cs new file mode 100644 index 000000000..5623bf684 --- /dev/null +++ b/src/samples/WorkflowCore.Sample20/Steps/HelloWorld.cs @@ -0,0 +1,16 @@ +using System; +using System.Linq; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Sample20.Steps +{ + public class HelloWorld : StepBody + { + public override ExecutionResult Run(IStepExecutionContext context) + { + Console.WriteLine("Hello world"); + return ExecutionResult.Next(); + } + } +} diff --git a/src/samples/WorkflowCore.Sample20/WorkflowCore.Sample20.csproj b/src/samples/WorkflowCore.Sample20/WorkflowCore.Sample20.csproj new file mode 100644 index 000000000..660b47511 --- /dev/null +++ b/src/samples/WorkflowCore.Sample20/WorkflowCore.Sample20.csproj @@ -0,0 +1,20 @@ + + + + Exe + netcoreapp3.0 + + + + + + + + + + + + + + + diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario2.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario2.cs new file mode 100644 index 000000000..356f77402 --- /dev/null +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario2.cs @@ -0,0 +1,75 @@ +using System; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using Xunit; +using FluentAssertions; +using System.Linq; +using WorkflowCore.Testing; + +namespace WorkflowCore.IntegrationTests.Scenarios +{ + public class ActivityScenario2 : WorkflowTest + { + public class MyDataClass + { + public object ActivityInput { get; set; } + public object ActivityOutput { get; set; } + } + + public class ActivityInput + { + public string Value1 { get; set; } + public int Value2 { get; set; } + } + + public class ActivityOutput + { + public string Value1 { get; set; } + public int Value2 { get; set; } + } + + public class ActivityWorkflow : IWorkflow + { + public string Id => "ActivityWorkflow"; + public int Version => 1; + public void Build(IWorkflowBuilder builder) + { + builder + .StartWith(context => ExecutionResult.Next()) + .Activity((_, context) => "act-1-" + context.Workflow.Id, data => data.ActivityInput) + .Output(data => data.ActivityOutput, step => step.Result); + } + } + + public ActivityScenario2() + { + Setup(); + } + + [Fact] + public void Scenario() + { + // compound key + var workflowId = StartWorkflow(new MyDataClass { ActivityInput = new ActivityInput { Value1 = "a", Value2 = 1 } }); + var activity = Host.GetPendingActivity("act-1-" + workflowId, "worker1", TimeSpan.FromSeconds(30)).Result; + + if (activity != null) + { + var actInput = (ActivityInput)activity.Parameters; + Host.SubmitActivitySuccess(activity.Token, new ActivityOutput + { + Value1 = actInput.Value1 + "1", + Value2 = actInput.Value2 + 1 + }); + } + + WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); + GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); + UnhandledStepErrors.Count.Should().Be(0); + GetData(workflowId).ActivityOutput.Should().BeOfType(); + var outData = (GetData(workflowId).ActivityOutput as ActivityOutput); + outData.Value1.Should().Be("a1"); + outData.Value2.Should().Be(2); + } + } +} From 42fdc797b387c3bac3ddd3e9d96568ba4fd5e694 Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Thu, 3 Jun 2021 11:15:38 +0300 Subject: [PATCH 137/342] Allow choose name of container for Cosmos DB --- .../Interface/ICosmosDbProvisioner.cs | 5 +-- .../ServiceCollectionExtensions.cs | 15 ++++++-- .../Services/CosmosDbPersistenceProvider.cs | 30 ++++++++-------- .../Services/CosmosDbProvisioner.cs | 22 ++++++------ .../Services/CosmosDbStorageOptions.cs | 35 +++++++++++++++++++ .../WorkflowCore.Providers.Azure.csproj | 4 +-- 6 files changed, 79 insertions(+), 32 deletions(-) create mode 100644 src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbStorageOptions.cs diff --git a/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbProvisioner.cs b/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbProvisioner.cs index 67a738971..d24cca4d8 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbProvisioner.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Interface/ICosmosDbProvisioner.cs @@ -1,9 +1,10 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; namespace WorkflowCore.Providers.Azure.Interface { public interface ICosmosDbProvisioner { - Task Provision(string dbId); + Task Provision(string dbId, CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs index 96fff8f1d..92718cb95 100644 --- a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs @@ -26,11 +26,20 @@ public static WorkflowOptions UseAzureServiceBusEventHub( return options; } - public static WorkflowOptions UseCosmosDbPersistence(this WorkflowOptions options, string connectionString, string databaseId) + public static WorkflowOptions UseCosmosDbPersistence( + this WorkflowOptions options, + string connectionString, + string databaseId, + CosmosDbStorageOptions cosmosDbStorageOptions = null) { + if (cosmosDbStorageOptions == null) + { + cosmosDbStorageOptions = new CosmosDbStorageOptions(); + } + options.Services.AddSingleton(sp => new CosmosClientFactory(connectionString)); - options.Services.AddTransient(sp => new CosmosDbProvisioner(sp.GetService(), sp.GetService())); - options.UsePersistence(sp => new CosmosDbPersistenceProvider(sp.GetService(), databaseId, sp.GetService())); + options.Services.AddTransient(sp => new CosmosDbProvisioner(sp.GetService(), cosmosDbStorageOptions)); + options.UsePersistence(sp => new CosmosDbPersistenceProvider(sp.GetService(), databaseId, sp.GetService(), cosmosDbStorageOptions)); return options; } } diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs index aa5d62ce0..36e51b86c 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs @@ -14,25 +14,25 @@ namespace WorkflowCore.Providers.Azure.Services { public class CosmosDbPersistenceProvider : IPersistenceProvider { - public const string WorkflowContainerName = "workflows"; - public const string EventContainerName = "events"; - public const string SubscriptionContainerName = "subscriptions"; - - private ICosmosDbProvisioner _provisioner; - private string _dbId; - private ICosmosClientFactory _clientFactory; - private Lazy _workflowContainer; - private Lazy _eventContainer; - private Lazy _subscriptionContainer; - - public CosmosDbPersistenceProvider(ICosmosClientFactory clientFactory, string dbId, ICosmosDbProvisioner provisioner) + private readonly ICosmosDbProvisioner _provisioner; + private readonly string _dbId; + private readonly ICosmosClientFactory _clientFactory; + private readonly Lazy _workflowContainer; + private readonly Lazy _eventContainer; + private readonly Lazy _subscriptionContainer; + + public CosmosDbPersistenceProvider( + ICosmosClientFactory clientFactory, + string dbId, + ICosmosDbProvisioner provisioner, + CosmosDbStorageOptions cosmosDbStorageOptions) { _provisioner = provisioner; _dbId = dbId; _clientFactory = clientFactory; - _workflowContainer = new Lazy(() => _clientFactory.GetCosmosClient().GetDatabase(_dbId).GetContainer(WorkflowContainerName)); - _eventContainer = new Lazy(() => _clientFactory.GetCosmosClient().GetDatabase(_dbId).GetContainer(EventContainerName)); - _subscriptionContainer = new Lazy(() => _clientFactory.GetCosmosClient().GetDatabase(_dbId).GetContainer(SubscriptionContainerName)); + _workflowContainer = new Lazy(() => _clientFactory.GetCosmosClient().GetDatabase(_dbId).GetContainer(cosmosDbStorageOptions.WorkflowContainerName)); + _eventContainer = new Lazy(() => _clientFactory.GetCosmosClient().GetDatabase(_dbId).GetContainer(cosmosDbStorageOptions.EventContainerName)); + _subscriptionContainer = new Lazy(() => _clientFactory.GetCosmosClient().GetDatabase(_dbId).GetContainer(cosmosDbStorageOptions.SubscriptionContainerName)); } public async Task ClearSubscriptionToken(string eventSubscriptionId, string token, CancellationToken cancellationToken = default) diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs index 08e51c2f4..54aa21435 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbProvisioner.cs @@ -1,35 +1,37 @@ -using System; +using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos; -using Microsoft.Extensions.Logging; using WorkflowCore.Providers.Azure.Interface; namespace WorkflowCore.Providers.Azure.Services { public class CosmosDbProvisioner : ICosmosDbProvisioner { + private readonly ICosmosClientFactory _clientFactory; + private readonly CosmosDbStorageOptions _cosmosDbStorageOptions; - private ICosmosClientFactory _clientFactory; - - public CosmosDbProvisioner(ICosmosClientFactory clientFactory, ILoggerFactory loggerFactory) + public CosmosDbProvisioner( + ICosmosClientFactory clientFactory, + CosmosDbStorageOptions cosmosDbStorageOptions) { _clientFactory = clientFactory; + _cosmosDbStorageOptions = cosmosDbStorageOptions; } - public async Task Provision(string dbId) + public async Task Provision(string dbId, CancellationToken cancellationToken = default) { - var dbResp = await _clientFactory.GetCosmosClient().CreateDatabaseIfNotExistsAsync(dbId); + var dbResp = await _clientFactory.GetCosmosClient().CreateDatabaseIfNotExistsAsync(dbId, cancellationToken: cancellationToken); var wfIndexPolicy = new IndexingPolicy(); wfIndexPolicy.IncludedPaths.Add(new IncludedPath { Path = @"/*" }); wfIndexPolicy.ExcludedPaths.Add(new ExcludedPath { Path = @"/ExecutionPointers/?" }); Task.WaitAll( - dbResp.Database.CreateContainerIfNotExistsAsync(new ContainerProperties(CosmosDbPersistenceProvider.WorkflowContainerName, @"/id") + dbResp.Database.CreateContainerIfNotExistsAsync(new ContainerProperties(_cosmosDbStorageOptions.WorkflowContainerName, @"/id") { IndexingPolicy = wfIndexPolicy }), - dbResp.Database.CreateContainerIfNotExistsAsync(new ContainerProperties(CosmosDbPersistenceProvider.EventContainerName, @"/id")), - dbResp.Database.CreateContainerIfNotExistsAsync(new ContainerProperties(CosmosDbPersistenceProvider.SubscriptionContainerName, @"/id")) + dbResp.Database.CreateContainerIfNotExistsAsync(new ContainerProperties(_cosmosDbStorageOptions.EventContainerName, @"/id")), + dbResp.Database.CreateContainerIfNotExistsAsync(new ContainerProperties(_cosmosDbStorageOptions.SubscriptionContainerName, @"/id")) ); } } diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbStorageOptions.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbStorageOptions.cs new file mode 100644 index 000000000..fc89c89b0 --- /dev/null +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbStorageOptions.cs @@ -0,0 +1,35 @@ +namespace WorkflowCore.Providers.Azure.Services +{ + public sealed class CosmosDbStorageOptions + { + /// + /// The default name of workflow container. + /// + public const string DefaultWorkflowContainerName = "workflows"; + + /// + /// The name of Workflow container in Cosmos DB. + /// + public string WorkflowContainerName { get; set; } = DefaultWorkflowContainerName; + + /// + /// The default name of event container. + /// + public const string DefaultEventContainerName = "events"; + + /// + /// The name of Event container in Cosmos DB. + /// + public string EventContainerName { get; set; } = DefaultEventContainerName; + + /// + /// The default name of subscription container. + /// + public const string DefaultSubscriptionContainerName = "subscriptions"; + + /// + /// The name of Subscription container in Cosmos DB. + /// + public string SubscriptionContainerName { get; set; } = DefaultSubscriptionContainerName; + } +} diff --git a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj index dc7e5609a..cedd72024 100644 --- a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj +++ b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj @@ -16,9 +16,9 @@ - + - + From 2c594a00c1d1c8053783f36cbb6103dd0cd878b7 Mon Sep 17 00:00:00 2001 From: "Simon A. Eugster" Date: Wed, 9 Jun 2021 09:44:09 +0200 Subject: [PATCH 138/342] Fix lifecycle events when restarting Workflow Core --- WorkflowCore.sln | 2 +- .../Interface/IDistributedLockProvider.cs | 6 +++ .../Services/LifeCycleEventPublisher.cs | 7 ++- src/WorkflowCore/Services/WorkflowHost.cs | 10 +++- .../Services/LifeCycleEventPublisherTests.cs | 54 +++++++++++++++++++ 5 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 test/WorkflowCore.UnitTests/Services/LifeCycleEventPublisherTests.cs diff --git a/WorkflowCore.sln b/WorkflowCore.sln index be18fd721..58387d6ed 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -7,7 +7,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EF47161E-E39 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F6AC9AEB-24EF-475A-B190-AA4D9E01270A}" ProjectSection(SolutionItems) = preProject - readme.md = readme.md + README.md = README.md EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{5080DB09-CBE8-4C45-9957-C3BB7651755E}" diff --git a/src/WorkflowCore/Interface/IDistributedLockProvider.cs b/src/WorkflowCore/Interface/IDistributedLockProvider.cs index 3c2018e42..498fafe5b 100644 --- a/src/WorkflowCore/Interface/IDistributedLockProvider.cs +++ b/src/WorkflowCore/Interface/IDistributedLockProvider.cs @@ -9,6 +9,12 @@ namespace WorkflowCore.Interface /// public interface IDistributedLockProvider { + /// + /// Acquire a lock on the specified resource. + /// + /// Resource ID to lock. + /// + /// `true`, if the lock was acquired. Task AcquireLock(string Id, CancellationToken cancellationToken); Task ReleaseLock(string Id); diff --git a/src/WorkflowCore/Services/LifeCycleEventPublisher.cs b/src/WorkflowCore/Services/LifeCycleEventPublisher.cs index ffebb332e..1dce43e4c 100644 --- a/src/WorkflowCore/Services/LifeCycleEventPublisher.cs +++ b/src/WorkflowCore/Services/LifeCycleEventPublisher.cs @@ -11,7 +11,7 @@ public class LifeCycleEventPublisher : ILifeCycleEventPublisher, IDisposable { private readonly ILifeCycleEventHub _eventHub; private readonly ILogger _logger; - private readonly BlockingCollection _outbox; + private BlockingCollection _outbox; private Task _dispatchTask; public LifeCycleEventPublisher(ILifeCycleEventHub eventHub, ILoggerFactory loggerFactory) @@ -36,6 +36,11 @@ public void Start() throw new InvalidOperationException(); } + if (_outbox.IsAddingCompleted) + { + _outbox = new BlockingCollection(); + } + _dispatchTask = new Task(Execute); _dispatchTask.Start(); } diff --git a/src/WorkflowCore/Services/WorkflowHost.cs b/src/WorkflowCore/Services/WorkflowHost.cs index 2a7fcc330..ca5e04b2f 100644 --- a/src/WorkflowCore/Services/WorkflowHost.cs +++ b/src/WorkflowCore/Services/WorkflowHost.cs @@ -47,7 +47,6 @@ public WorkflowHost(IPersistenceProvider persistenceStore, IQueueProvider queueP _searchIndex = searchIndex; _activityController = activityController; _lifeCycleEventHub = lifeCycleEventHub; - _lifeCycleEventHub.Subscribe(HandleLifeCycleEvent); } public Task StartWorkflow(string workflowId, object data = null, string reference=null) @@ -91,6 +90,10 @@ public async Task StartAsync(CancellationToken cancellationToken) await _lifeCycleEventHub.Start(); await _searchIndex.Start(); + // Event subscriptions are removed when stopping the event hub. + // Add them when starting. + AddEventSubscriptions(); + Logger.LogInformation("Starting background tasks"); foreach (var task in _backgroundTasks) @@ -181,5 +184,10 @@ public Task SubmitActivityFailure(string token, object result) { return _activityController.SubmitActivityFailure(token, result); } + + private void AddEventSubscriptions() + { + _lifeCycleEventHub.Subscribe(HandleLifeCycleEvent); + } } } diff --git a/test/WorkflowCore.UnitTests/Services/LifeCycleEventPublisherTests.cs b/test/WorkflowCore.UnitTests/Services/LifeCycleEventPublisherTests.cs new file mode 100644 index 000000000..bfee3ad07 --- /dev/null +++ b/test/WorkflowCore.UnitTests/Services/LifeCycleEventPublisherTests.cs @@ -0,0 +1,54 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Moq; +using WorkflowCore.Interface; +using WorkflowCore.Models.LifeCycleEvents; +using WorkflowCore.Services; +using Xunit; + +namespace WorkflowCore.UnitTests.Services +{ + public class LifeCycleEventPublisherTests + { + [Fact(DisplayName = "Notifications should be published when the publisher is running")] + public async Task PublishNotification_WhenStarted_PublishesNotification() + { + // Arrange + var wasCalled = new TaskCompletionSource(); + var eventHubMock = new Mock(); + eventHubMock + .Setup(hub => hub.PublishNotification(It.IsAny())) + .Callback(() => wasCalled.SetResult(true)); + LifeCycleEventPublisher publisher = new LifeCycleEventPublisher(eventHubMock.Object, new LoggerFactory()); + + // Act + publisher.Start(); + publisher.PublishNotification(new StepCompleted()); + + // Assert + await wasCalled.Task; + } + + [Fact(DisplayName = "Notifications should be published when the publisher is running")] + public async Task PublishNotification_WhenRestarted_PublishesNotification() + { + // Arrange + var wasCalled = new TaskCompletionSource(); + var eventHubMock = new Mock(); + eventHubMock + .Setup(hub => hub.PublishNotification(It.IsAny())) + .Callback(() => wasCalled.SetResult(true)); + LifeCycleEventPublisher publisher = new LifeCycleEventPublisher(eventHubMock.Object, new LoggerFactory()); + + // Act + publisher.Start(); + publisher.Stop(); + publisher.Start(); + publisher.PublishNotification(new StepCompleted()); + + // Assert + await wasCalled.Task; + } + } +} \ No newline at end of file From 66b6e45673b6967d4ea990e728f303da98b4c0b5 Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Wed, 23 Jun 2021 18:53:06 +0300 Subject: [PATCH 139/342] Wait until lock will be postponed --- .../Services/BackgroundTasks/WorkflowConsumer.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index 7c0637482..2faba7b87 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -89,8 +89,19 @@ private async Task SubscribeEvent(EventSubscription subscription, IPersistencePr if (subscription.EventName != Event.EventTypeActivity) { var events = await persistenceStore.GetEvents(subscription.EventName, subscription.EventKey, subscription.SubscribeAsOf, cancellationToken); + foreach (var evt in events) { + var locked = await _lockProvider.AcquireLock($"evt:{evt}", cancellationToken); + int attempt = 0; + while (locked && attempt < 10) + { + locked = await _lockProvider.AcquireLock($"evt:{evt}", cancellationToken); + await Task.Delay(Options.IdleTime); + + attempt++; + } + await persistenceStore.MarkEventUnprocessed(evt, cancellationToken); await QueueProvider.QueueWork(evt, QueueType.Event); } From 2746d0529b446c0d64d7e0d032508ea4b1ff4150 Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Wed, 23 Jun 2021 19:49:20 +0300 Subject: [PATCH 140/342] Use Lock on event subscription --- .../BackgroundTasks/WorkflowConsumer.cs | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index 2faba7b87..4253678cc 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -92,18 +92,30 @@ private async Task SubscribeEvent(EventSubscription subscription, IPersistencePr foreach (var evt in events) { - var locked = await _lockProvider.AcquireLock($"evt:{evt}", cancellationToken); - int attempt = 0; - while (locked && attempt < 10) + var eventKey = $"evt:{evt}"; + bool acquiredLock = false; + try { - locked = await _lockProvider.AcquireLock($"evt:{evt}", cancellationToken); - await Task.Delay(Options.IdleTime); + acquiredLock = await _lockProvider.AcquireLock(eventKey, cancellationToken); + int attempt = 0; + while (!acquiredLock && attempt < 10) + { + acquiredLock = await _lockProvider.AcquireLock(eventKey, cancellationToken); + await Task.Delay(Options.IdleTime); - attempt++; - } + attempt++; + } - await persistenceStore.MarkEventUnprocessed(evt, cancellationToken); - await QueueProvider.QueueWork(evt, QueueType.Event); + await persistenceStore.MarkEventUnprocessed(evt, cancellationToken); + await QueueProvider.QueueWork(evt, QueueType.Event); + } + finally + { + if (acquiredLock) + { + await _lockProvider.ReleaseLock(eventKey); + } + } } } } From 0ac318dd37f814bd6c442409fe44dbe41ddf06db Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 23 Jun 2021 22:16:47 -0700 Subject: [PATCH 141/342] bump version --- test/WorkflowCore.Testing/WorkflowCore.Testing.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj index fd6508887..4449e3fa6 100644 --- a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj +++ b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj @@ -2,9 +2,9 @@ netstandard2.0 - 2.3.0 - 2.3.0.0 - 2.3.0.0 + 3.5.0 + 3.5.0.0 + 3.5.0.0 Facilitates testing of workflows built on Workflow-Core From 91ee43d3fd7cf1d2dbd4bfc910d8f71d75f811c2 Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Tue, 29 Jun 2021 17:36:41 +0300 Subject: [PATCH 142/342] Fix greylist foerever stack issue --- .../Services/BackgroundTasks/EventConsumer.cs | 8 +++++++- .../Services/BackgroundTasks/RunnablePoller.cs | 1 - 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs index f533a32ff..9635df3ad 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs @@ -74,7 +74,13 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance complete = complete && await SeedSubscription(evt, sub, toQueue, cancellationToken); if (complete) + { await _eventRepository.MarkEventProcessed(itemId, cancellationToken); + } + else + { + _greylist.Remove($"evt:{evt.Id}"); + } foreach (var eventId in toQueue) await QueueProvider.QueueWork(eventId, QueueType.Event); @@ -87,7 +93,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance } private async Task SeedSubscription(Event evt, EventSubscription sub, HashSet toQueue, CancellationToken cancellationToken) - { + { foreach (var eventId in await _eventRepository.GetEvents(sub.EventName, sub.EventKey, sub.SubscribeAsOf, cancellationToken)) { if (eventId == evt.Id) diff --git a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs index 6a6bdf79c..9d5edc575 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs @@ -93,7 +93,6 @@ private async void PollRunnables(object target) if (_greylist.Contains($"evt:{item}")) { _logger.LogDebug($"Got greylisted event {item}"); - _greylist.Add($"evt:{item}"); continue; } _logger.LogDebug($"Got unprocessed event {item}"); From e67e98c0f69bb6039e6c515c0405f15d0e6acd03 Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Tue, 29 Jun 2021 17:41:00 +0300 Subject: [PATCH 143/342] Greylist fixes in workflow consumer --- .../Services/BackgroundTasks/WorkflowConsumer.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index 4253678cc..23227d95d 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -84,7 +84,7 @@ private async Task SubscribeEvent(EventSubscription subscription, IPersistencePr { //TODO: move to own class Logger.LogDebug("Subscribing to event {0} {1} for workflow {2} step {3}", subscription.EventName, subscription.EventKey, subscription.WorkflowId, subscription.StepId); - + await persistenceStore.CreateEventSubscription(subscription, cancellationToken); if (subscription.EventName != Event.EventTypeActivity) { @@ -101,13 +101,21 @@ private async Task SubscribeEvent(EventSubscription subscription, IPersistencePr while (!acquiredLock && attempt < 10) { acquiredLock = await _lockProvider.AcquireLock(eventKey, cancellationToken); - await Task.Delay(Options.IdleTime); + await Task.Delay(Options.IdleTime, cancellationToken); attempt++; } - await persistenceStore.MarkEventUnprocessed(evt, cancellationToken); - await QueueProvider.QueueWork(evt, QueueType.Event); + if (!acquiredLock) + { + Logger.LogWarning($"Failed to lock {evt}"); + } + else + { + await persistenceStore.MarkEventUnprocessed(evt, cancellationToken); + await QueueProvider.QueueWork(evt, QueueType.Event); + _greylist.Remove(eventKey); + } } finally { From 112fdee8eb59edb46c09d6ff743ceaa4d0c3daf4 Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Fri, 2 Jul 2021 10:37:24 +0300 Subject: [PATCH 144/342] Improve delay, change greylist clean --- .../Services/BackgroundTasks/WorkflowConsumer.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index 23227d95d..6e5c1d3c1 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -35,10 +35,10 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance Logger.LogInformation("Workflow locked {0}", itemId); return; } - + WorkflowInstance workflow = null; WorkflowExecutorResult result = null; - + try { cancellationToken.ThrowIfCancellationRequested(); @@ -77,9 +77,9 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance } } } - + } - + private async Task SubscribeEvent(EventSubscription subscription, IPersistenceProvider persistenceStore, CancellationToken cancellationToken) { //TODO: move to own class @@ -100,8 +100,8 @@ private async Task SubscribeEvent(EventSubscription subscription, IPersistencePr int attempt = 0; while (!acquiredLock && attempt < 10) { - acquiredLock = await _lockProvider.AcquireLock(eventKey, cancellationToken); await Task.Delay(Options.IdleTime, cancellationToken); + acquiredLock = await _lockProvider.AcquireLock(eventKey, cancellationToken); attempt++; } @@ -112,9 +112,9 @@ private async Task SubscribeEvent(EventSubscription subscription, IPersistencePr } else { + _greylist.Remove(eventKey); await persistenceStore.MarkEventUnprocessed(evt, cancellationToken); await QueueProvider.QueueWork(evt, QueueType.Event); - _greylist.Remove(eventKey); } } finally From 782ca9aab7a1ca9eff312be0ede5dc9c0e484052 Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Fri, 2 Jul 2021 10:59:25 +0300 Subject: [PATCH 145/342] Adding unit test to cover Parallel event scenario --- .../Scenarios/ParallelEventsScenario.cs | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 test/WorkflowCore.IntegrationTests/Scenarios/ParallelEventsScenario.cs diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ParallelEventsScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ParallelEventsScenario.cs new file mode 100644 index 000000000..d7176c880 --- /dev/null +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ParallelEventsScenario.cs @@ -0,0 +1,91 @@ +using System; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using Xunit; +using FluentAssertions; +using WorkflowCore.Testing; +using System.Threading; + +namespace WorkflowCore.IntegrationTests.Scenarios +{ + public sealed class ParallelEventsScenario + : WorkflowTest + { + private const string EVENT_KEY = nameof(EVENT_KEY); + + public class MyDataClass + { + public string StrValue1 { get; set; } + public string StrValue2 { get; set; } + } + + public class ParallelEventsWorkflow : IWorkflow + { + public string Id => "EventWorkflow"; + public int Version => 1; + public void Build(IWorkflowBuilder builder) + { + builder + .StartWith(context => ExecutionResult.Next()) + .Parallel() + .Do(then => + then.WaitFor("Event1", data => EVENT_KEY).Then(x => + { + Thread.Sleep(300); + return ExecutionResult.Next(); + })) + .Do(then => + then.WaitFor("Event2", data => EVENT_KEY).Then(x => + { + Thread.Sleep(100); + return ExecutionResult.Next(); + })) + .Do(then => + then.WaitFor("Event3", data => EVENT_KEY).Then(x => + { + Thread.Sleep(1000); + return ExecutionResult.Next(); + })) + .Do(then => + then.WaitFor("Event4", data => EVENT_KEY).Then(x => + { + Thread.Sleep(100); + return ExecutionResult.Next(); + })) + .Do(then => + then.WaitFor("Event5", data => EVENT_KEY).Then(x => + { + Thread.Sleep(100); + return ExecutionResult.Next(); + })) + .Join() + .Then(x => + { + return ExecutionResult.Next(); + }); + } + } + + public ParallelEventsScenario() + { + Setup(); + } + + [Fact] + public void Scenario() + { + var eventKey = Guid.NewGuid().ToString(); + var workflowId = StartWorkflow(new MyDataClass { StrValue1 = eventKey, StrValue2 = eventKey }); + Host.PublishEvent("Event1", EVENT_KEY, "Pass1"); + Host.PublishEvent("Event2", EVENT_KEY, "Pass2"); + Host.PublishEvent("Event3", EVENT_KEY, "Pass3"); + Host.PublishEvent("Event4", EVENT_KEY, "Pass4"); + Host.PublishEvent("Event5", EVENT_KEY, "Pass5"); + + WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); + + GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); + UnhandledStepErrors.Count.Should().Be(0); + } + } +} From f049bd5c1bb77784c36fa192acccf3d5f3a0b652 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 2 Jul 2021 19:58:37 -0700 Subject: [PATCH 146/342] bump versions --- src/Directory.Build.props | 8 ++++---- .../WorkflowCore.Sample01/HelloWorldWorkflow.cs | 2 ++ test/WorkflowCore.Testing/WorkflowCore.Testing.csproj | 7 +++---- test/WorkflowCore.Testing/WorkflowTest.cs | 10 ---------- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index f8f086812..acd8f26db 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.5.0 - 3.5.0.0 - 3.5.0.0 + 3.5.1 + 3.5.1.0 + 3.5.1.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.5.0 + 3.5.1 diff --git a/src/samples/WorkflowCore.Sample01/HelloWorldWorkflow.cs b/src/samples/WorkflowCore.Sample01/HelloWorldWorkflow.cs index f268b6307..157966f18 100644 --- a/src/samples/WorkflowCore.Sample01/HelloWorldWorkflow.cs +++ b/src/samples/WorkflowCore.Sample01/HelloWorldWorkflow.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using WorkflowCore.Interface; +using WorkflowCore.Models; using WorkflowCore.Sample01.Steps; namespace WorkflowCore.Sample01 @@ -10,6 +11,7 @@ public class HelloWorldWorkflow : IWorkflow public void Build(IWorkflowBuilder builder) { builder + .UseDefaultErrorBehavior(WorkflowErrorHandling.Suspend) .StartWith() .Then(); } diff --git a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj index 4449e3fa6..9b89e8d60 100644 --- a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj +++ b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj @@ -2,9 +2,9 @@ netstandard2.0 - 3.5.0 - 3.5.0.0 - 3.5.0.0 + 3.5.1 + 3.5.1.0 + 3.5.1.0 Facilitates testing of workflows built on Workflow-Core @@ -12,7 +12,6 @@ - diff --git a/test/WorkflowCore.Testing/WorkflowTest.cs b/test/WorkflowCore.Testing/WorkflowTest.cs index 84db06002..7bd3587c2 100644 --- a/test/WorkflowCore.Testing/WorkflowTest.cs +++ b/test/WorkflowCore.Testing/WorkflowTest.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using MongoDB.Bson.Serialization; using WorkflowCore.Interface; using WorkflowCore.Models; @@ -28,15 +27,6 @@ protected virtual void Setup(bool registerClassMap = false) var serviceProvider = services.BuildServiceProvider(); - //config logging - var loggerFactory = serviceProvider.GetService(); - //loggerFactory.AddConsole(LogLevel.Debug); - - if (registerClassMap && !BsonClassMap.IsClassMapRegistered(typeof(TData))) - { - BsonClassMap.RegisterClassMap(map => map.AutoMap()); - } - PersistenceProvider = serviceProvider.GetService(); Host = serviceProvider.GetService(); Host.RegisterWorkflow(); From 06470ce83446a970ff95f2f070793cefa7f6e5cc Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 2 Jul 2021 20:13:56 -0700 Subject: [PATCH 147/342] remove mongo dependency from testing package --- src/samples/WorkflowCore.TestSample01/NUnitTest.cs | 2 +- .../Scenarios/DataIOScenario.cs | 2 +- test/WorkflowCore.Testing/WorkflowCore.Testing.csproj | 6 +++--- test/WorkflowCore.Testing/WorkflowTest.cs | 2 +- .../Scenarios/MongoDataScenario.cs | 8 +++++++- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/samples/WorkflowCore.TestSample01/NUnitTest.cs b/src/samples/WorkflowCore.TestSample01/NUnitTest.cs index 91be04202..167c97441 100644 --- a/src/samples/WorkflowCore.TestSample01/NUnitTest.cs +++ b/src/samples/WorkflowCore.TestSample01/NUnitTest.cs @@ -13,7 +13,7 @@ public class NUnitTest : WorkflowTest [SetUp] protected void Setup() { - base.Setup(false); + base.Setup(); } [Test] diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs index d8a12724d..1d4157c96 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/DataIOScenario.cs @@ -53,7 +53,7 @@ public void Build(IWorkflowBuilder builder) public DataIOScenario() { - Setup(true); + Setup(); } [Fact] diff --git a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj index 9b89e8d60..6102c9892 100644 --- a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj +++ b/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj @@ -2,9 +2,9 @@ netstandard2.0 - 3.5.1 - 3.5.1.0 - 3.5.1.0 + 3.5.2 + 3.5.2.0 + 3.5.2.0 Facilitates testing of workflows built on Workflow-Core diff --git a/test/WorkflowCore.Testing/WorkflowTest.cs b/test/WorkflowCore.Testing/WorkflowTest.cs index 7bd3587c2..46a6d0ce8 100644 --- a/test/WorkflowCore.Testing/WorkflowTest.cs +++ b/test/WorkflowCore.Testing/WorkflowTest.cs @@ -18,7 +18,7 @@ public abstract class WorkflowTest : IDisposable protected IPersistenceProvider PersistenceProvider; protected List UnhandledStepErrors = new List(); - protected virtual void Setup(bool registerClassMap = false) + protected virtual void Setup() { //setup dependency injection IServiceCollection services = new ServiceCollection(); diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDataScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDataScenario.cs index 468915f75..e842f6fee 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDataScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDataScenario.cs @@ -1,5 +1,6 @@ using System; using Microsoft.Extensions.DependencyInjection; +using MongoDB.Bson.Serialization; using WorkflowCore.IntegrationTests.Scenarios; using Xunit; @@ -7,7 +8,12 @@ namespace WorkflowCore.Tests.MongoDB.Scenarios { [Collection("Mongo collection")] public class MongoDataScenario : DataIOScenario - { + { + public MongoDataScenario() : base() + { + BsonClassMap.RegisterClassMap(map => map.AutoMap()); + } + protected override void ConfigureServices(IServiceCollection services) { services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); From a94f0b1875fbe7938ef073ee4e602fe8cb92486c Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 6 Jul 2021 13:52:29 +0200 Subject: [PATCH 148/342] Allow mongo client configuration --- .../ServiceCollectionExtensions.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Persistence.MongoDB/ServiceCollectionExtensions.cs index 34e7857c8..87b0e689e 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/ServiceCollectionExtensions.cs @@ -9,17 +9,25 @@ namespace Microsoft.Extensions.DependencyInjection { public static class ServiceCollectionExtensions { - public static WorkflowOptions UseMongoDB(this WorkflowOptions options, string mongoUrl, string databaseName) + public static WorkflowOptions UseMongoDB( + this WorkflowOptions options, + string mongoUrl, + string databaseName, + Action configureClient = default) { options.UsePersistence(sp => { - var client = new MongoClient(mongoUrl); + var mongoClientSettings = MongoClientSettings.FromConnectionString(mongoUrl); + configureClient?.Invoke(mongoClientSettings); + var client = new MongoClient(mongoClientSettings); var db = client.GetDatabase(databaseName); return new MongoPersistenceProvider(db); }); options.Services.AddTransient(sp => { - var client = new MongoClient(mongoUrl); + var mongoClientSettings = MongoClientSettings.FromConnectionString(mongoUrl); + configureClient?.Invoke(mongoClientSettings); + var client = new MongoClient(mongoClientSettings); var db = client.GetDatabase(databaseName); return new WorkflowPurger(db); }); From b194abe80449c96afee0db6f90b79b88db42d7ae Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Sun, 11 Jul 2021 12:56:14 +0300 Subject: [PATCH 149/342] Add AzureWorkflow purger --- src/WorkflowCore/Interface/IWorkflowPurger.cs | 3 +- .../Services/WorkflowPurger.cs | 7 ++-- .../Services/WorkflowPurger.cs | 8 ++-- .../Services/WorkflowPurger.cs | 10 ++--- .../ServiceCollectionExtensions.cs | 2 + .../Services/WorkflowPurger.cs | 42 +++++++++++++++++++ 6 files changed, 60 insertions(+), 12 deletions(-) create mode 100644 src/providers/WorkflowCore.Providers.Azure/Services/WorkflowPurger.cs diff --git a/src/WorkflowCore/Interface/IWorkflowPurger.cs b/src/WorkflowCore/Interface/IWorkflowPurger.cs index a85d9a0bf..42f6ba85f 100644 --- a/src/WorkflowCore/Interface/IWorkflowPurger.cs +++ b/src/WorkflowCore/Interface/IWorkflowPurger.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; using WorkflowCore.Models; @@ -6,6 +7,6 @@ namespace WorkflowCore.Interface { public interface IWorkflowPurger { - Task PurgeWorkflows(WorkflowStatus status, DateTime olderThan); + Task PurgeWorkflows(WorkflowStatus status, DateTime olderThan, CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowPurger.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowPurger.cs index 31384be84..904895809 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowPurger.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowPurger.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using WorkflowCore.Interface; @@ -18,12 +19,12 @@ public WorkflowPurger(IWorkflowDbContextFactory contextFactory) _contextFactory = contextFactory; } - public async Task PurgeWorkflows(WorkflowStatus status, DateTime olderThan) + public async Task PurgeWorkflows(WorkflowStatus status, DateTime olderThan, CancellationToken cancellationToken = default) { var olderThanUtc = olderThan.ToUniversalTime(); using (var db = ConstructDbContext()) { - var workflows = await db.Set().Where(x => x.Status == status && x.CompleteTime < olderThanUtc).ToListAsync(); + var workflows = await db.Set().Where(x => x.Status == status && x.CompleteTime < olderThanUtc).ToListAsync(cancellationToken); foreach (var wf in workflows) { foreach (var pointer in wf.ExecutionPointers) @@ -38,7 +39,7 @@ public async Task PurgeWorkflows(WorkflowStatus status, DateTime olderThan) db.Remove(wf); } - await db.SaveChangesAsync(); + await db.SaveChangesAsync(cancellationToken); } } diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/WorkflowPurger.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/WorkflowPurger.cs index 85b1be31b..56343d3f6 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/WorkflowPurger.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/WorkflowPurger.cs @@ -3,24 +3,26 @@ using MongoDB.Driver; using WorkflowCore.Models; using WorkflowCore.Interface; +using System.Threading; namespace WorkflowCore.Persistence.MongoDB.Services { public class WorkflowPurger : IWorkflowPurger { private readonly IMongoDatabase _database; - private IMongoCollection WorkflowInstances => _database.GetCollection(MongoPersistenceProvider.WorkflowCollectionName); + private IMongoCollection WorkflowInstances => _database.GetCollection(MongoPersistenceProvider.WorkflowCollectionName); public WorkflowPurger(IMongoDatabase database) { _database = database; } - public async Task PurgeWorkflows(WorkflowStatus status, DateTime olderThan) + public async Task PurgeWorkflows(WorkflowStatus status, DateTime olderThan, CancellationToken cancellationToken = default) { var olderThanUtc = olderThan.ToUniversalTime(); - await WorkflowInstances.DeleteManyAsync(x => x.Status == status && x.CompleteTime < olderThanUtc); + await WorkflowInstances.DeleteManyAsync(x => x.Status == status + && x.CompleteTime < olderThanUtc, cancellationToken); } } } \ No newline at end of file diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/Services/WorkflowPurger.cs b/src/providers/WorkflowCore.Persistence.RavenDB/Services/WorkflowPurger.cs index f799fd6a5..c70fc09fd 100644 --- a/src/providers/WorkflowCore.Persistence.RavenDB/Services/WorkflowPurger.cs +++ b/src/providers/WorkflowCore.Persistence.RavenDB/Services/WorkflowPurger.cs @@ -3,9 +3,9 @@ using WorkflowCore.Models; using System.Threading.Tasks; using Raven.Client.Documents; -using System.Linq; using Raven.Client.Documents.Operations; using Raven.Client.Documents.Queries; +using System.Threading; namespace WorkflowCore.Persistence.RavenDB.Services { @@ -18,9 +18,9 @@ public WorkflowPurger(IDocumentStore database) _database = database; } - public async Task PurgeWorkflows(WorkflowStatus status, DateTime olderThan) + public async Task PurgeWorkflows(WorkflowStatus status, DateTime olderThan, CancellationToken cancellationToken = default) { - await DeleteWorkflowInstances(status, olderThan); + await DeleteWorkflowInstances(status, olderThan, cancellationToken); } @@ -28,11 +28,11 @@ public async Task PurgeWorkflows(WorkflowStatus status, DateTime olderThan) /// Delete all Workflow Documents /// /// - private Task DeleteWorkflowInstances(WorkflowStatus status, DateTime olderThan) + private Task DeleteWorkflowInstances(WorkflowStatus status, DateTime olderThan, CancellationToken cancellationToken = default) { var utcTime = olderThan.ToUniversalTime(); var queryToDelete = new IndexQuery { Query = $"FROM {nameof(WorkflowInstance)} where status = '{status}' and CompleteTime < '{olderThan}'" }; - return _database.Operations.SendAsync(new DeleteByQueryOperation(queryToDelete, new QueryOperationOptions { AllowStale = false })); + return _database.Operations.SendAsync(new DeleteByQueryOperation(queryToDelete, new QueryOperationOptions { AllowStale = false }), token: cancellationToken); } } } diff --git a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs index 92718cb95..897726e82 100644 --- a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.Logging; +using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Providers.Azure.Interface; using WorkflowCore.Providers.Azure.Services; @@ -39,6 +40,7 @@ public static WorkflowOptions UseCosmosDbPersistence( options.Services.AddSingleton(sp => new CosmosClientFactory(connectionString)); options.Services.AddTransient(sp => new CosmosDbProvisioner(sp.GetService(), cosmosDbStorageOptions)); + options.Services.AddTransient(sp => new WorkflowPurger(sp.GetService(), databaseId, cosmosDbStorageOptions)); options.UsePersistence(sp => new CosmosDbPersistenceProvider(sp.GetService(), databaseId, sp.GetService(), cosmosDbStorageOptions)); return options; } diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/WorkflowPurger.cs b/src/providers/WorkflowCore.Providers.Azure/Services/WorkflowPurger.cs new file mode 100644 index 000000000..64050f9f8 --- /dev/null +++ b/src/providers/WorkflowCore.Providers.Azure/Services/WorkflowPurger.cs @@ -0,0 +1,42 @@ +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Azure.Cosmos; +using Microsoft.Azure.Cosmos.Linq; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using WorkflowCore.Providers.Azure.Interface; +using WorkflowCore.Providers.Azure.Models; + +namespace WorkflowCore.Providers.Azure.Services +{ + public class WorkflowPurger : IWorkflowPurger + { + private readonly Lazy _workflowContainer; + + public WorkflowPurger(ICosmosClientFactory clientFactory, string dbId, CosmosDbStorageOptions cosmosDbStorageOptions) + { + _workflowContainer = new Lazy(() => clientFactory.GetCosmosClient() + .GetDatabase(dbId) + .GetContainer(cosmosDbStorageOptions.WorkflowContainerName)); + } + + public async Task PurgeWorkflows(WorkflowStatus status, DateTime olderThan, CancellationToken cancellationToken = default) + { + var olderThanUtc = olderThan.ToUniversalTime(); + using (FeedIterator feedIterator = _workflowContainer.Value.GetItemLinqQueryable() + .Where(x => x.Status == status && x.CompleteTime < olderThanUtc) + .ToFeedIterator()) + { + while (feedIterator.HasMoreResults) + { + foreach (var item in await feedIterator.ReadNextAsync(cancellationToken)) + { + await _workflowContainer.Value.DeleteItemAsync(item.id, new PartitionKey(item.id), cancellationToken: cancellationToken); + } + } + } + } + } +} From 2ff52820e9f58e8884034c370174e86f285f2f07 Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Sun, 11 Jul 2021 12:59:25 +0300 Subject: [PATCH 150/342] Rollback changes for Even subscription --- .../Services/BackgroundTasks/WorkflowConsumer.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index 2faba7b87..7c0637482 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -89,19 +89,8 @@ private async Task SubscribeEvent(EventSubscription subscription, IPersistencePr if (subscription.EventName != Event.EventTypeActivity) { var events = await persistenceStore.GetEvents(subscription.EventName, subscription.EventKey, subscription.SubscribeAsOf, cancellationToken); - foreach (var evt in events) { - var locked = await _lockProvider.AcquireLock($"evt:{evt}", cancellationToken); - int attempt = 0; - while (locked && attempt < 10) - { - locked = await _lockProvider.AcquireLock($"evt:{evt}", cancellationToken); - await Task.Delay(Options.IdleTime); - - attempt++; - } - await persistenceStore.MarkEventUnprocessed(evt, cancellationToken); await QueueProvider.QueueWork(evt, QueueType.Event); } From 5d890c069693fde7527458880d95fe70afb612c5 Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Sun, 11 Jul 2021 18:08:15 +0300 Subject: [PATCH 151/342] Change Scope for WorkflowPurger --- .../WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs index 897726e82..0aa1963e4 100644 --- a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs @@ -40,7 +40,7 @@ public static WorkflowOptions UseCosmosDbPersistence( options.Services.AddSingleton(sp => new CosmosClientFactory(connectionString)); options.Services.AddTransient(sp => new CosmosDbProvisioner(sp.GetService(), cosmosDbStorageOptions)); - options.Services.AddTransient(sp => new WorkflowPurger(sp.GetService(), databaseId, cosmosDbStorageOptions)); + options.Services.AddSingleton(sp => new WorkflowPurger(sp.GetService(), databaseId, cosmosDbStorageOptions)); options.UsePersistence(sp => new CosmosDbPersistenceProvider(sp.GetService(), databaseId, sp.GetService(), cosmosDbStorageOptions)); return options; } From ed0b7417d86c7d3931dd86be85cb1e5b612fb5ec Mon Sep 17 00:00:00 2001 From: slee_dtec Date: Thu, 15 Jul 2021 14:56:33 -0400 Subject: [PATCH 152/342] fix issue871 where child steps in the failed Saga container do not get retried when the suspended workflow is resumed --- src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs index 20ff0bab3..3cc3279ec 100755 --- a/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs @@ -29,6 +29,8 @@ public void Handle(WorkflowInstance workflow, WorkflowDefinition def, ExecutionP WorkflowDefinitionId = workflow.WorkflowDefinitionId, Version = workflow.Version }); + + step.PrimeForRetry(pointer); } } } From d6056150dd910798d6ec4f325e85f8312a132889 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Thu, 29 Jul 2021 22:06:29 -0700 Subject: [PATCH 153/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index acd8f26db..a02261928 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.5.1 - 3.5.1.0 - 3.5.1.0 + 3.5.2 + 3.5.2.0 + 3.5.2.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.5.1 + 3.5.2 From e85cdf318f5e003cf60d21cc001a7618bb82b2ae Mon Sep 17 00:00:00 2001 From: lyzerk Date: Fri, 30 Jul 2021 16:22:30 +0300 Subject: [PATCH 154/342] disable sample20 --- src/samples/WorkflowCore.Sample20/Program.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/samples/WorkflowCore.Sample20/Program.cs b/src/samples/WorkflowCore.Sample20/Program.cs index 69009fe98..4e8f1303f 100644 --- a/src/samples/WorkflowCore.Sample20/Program.cs +++ b/src/samples/WorkflowCore.Sample20/Program.cs @@ -9,7 +9,8 @@ class Program { static void Main(string[] args) { - var serviceProvider = ConfigureServices(); + // THE TEST DISABLED FOR THE BUILD TIME LIMIT + /*var serviceProvider = ConfigureServices(); //start the workflow host var host = serviceProvider.GetService(); @@ -29,7 +30,7 @@ static void Main(string[] args) } Console.ReadLine(); - host.Stop(); + host.Stop();*/ } private static IServiceProvider ConfigureServices() From 8082c624632775de1f66552ac755b5d6ea7739b8 Mon Sep 17 00:00:00 2001 From: lyzerk Date: Fri, 30 Jul 2021 17:04:31 +0300 Subject: [PATCH 155/342] remove sample20 --- WorkflowCore.sln | 9 +--- .../WorkflowCore.Sample20/ActivityWorkflow.cs | 29 ---------- src/samples/WorkflowCore.Sample20/Program.cs | 54 ------------------- src/samples/WorkflowCore.Sample20/README.md | 34 ------------ .../Steps/CustomMessage.cs | 19 ------- .../Steps/GoodbyeWorld.cs | 16 ------ .../WorkflowCore.Sample20/Steps/HelloWorld.cs | 16 ------ .../WorkflowCore.Sample20.csproj | 20 ------- 8 files changed, 1 insertion(+), 196 deletions(-) delete mode 100644 src/samples/WorkflowCore.Sample20/ActivityWorkflow.cs delete mode 100644 src/samples/WorkflowCore.Sample20/Program.cs delete mode 100644 src/samples/WorkflowCore.Sample20/README.md delete mode 100644 src/samples/WorkflowCore.Sample20/Steps/CustomMessage.cs delete mode 100644 src/samples/WorkflowCore.Sample20/Steps/GoodbyeWorld.cs delete mode 100644 src/samples/WorkflowCore.Sample20/Steps/HelloWorld.cs delete mode 100644 src/samples/WorkflowCore.Sample20/WorkflowCore.Sample20.csproj diff --git a/WorkflowCore.sln b/WorkflowCore.sln index 8bd5d6ca1..de509ed05 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -150,9 +150,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Tests.QueuePro EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample19", "src\samples\WorkflowCore.Sample19\WorkflowCore.Sample19.csproj", "{1223ED47-3E5E-4960-B70D-DFAF550F6666}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Persistence.RavenDB", "src\providers\WorkflowCore.Persistence.RavenDB\WorkflowCore.Persistence.RavenDB.csproj", "{AF205715-C8B7-42EF-BF14-AFC9E7F27242}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample20", "src\samples\WorkflowCore.Sample20\WorkflowCore.Sample20.csproj", "{68D1B955-1049-477B-A894-13FCB96C45DE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Persistence.RavenDB", "src\providers\WorkflowCore.Persistence.RavenDB\WorkflowCore.Persistence.RavenDB.csproj", "{AF205715-C8B7-42EF-BF14-AFC9E7F27242}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -376,10 +374,6 @@ Global {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Debug|Any CPU.Build.0 = Debug|Any CPU {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Release|Any CPU.ActiveCfg = Release|Any CPU {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Release|Any CPU.Build.0 = Release|Any CPU - {68D1B955-1049-477B-A894-13FCB96C45DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {68D1B955-1049-477B-A894-13FCB96C45DE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {68D1B955-1049-477B-A894-13FCB96C45DE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {68D1B955-1049-477B-A894-13FCB96C45DE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -442,7 +436,6 @@ Global {54DE20BA-EBA7-4BF0-9BD9-F03766849716} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} {1223ED47-3E5E-4960-B70D-DFAF550F6666} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} {AF205715-C8B7-42EF-BF14-AFC9E7F27242} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} - {68D1B955-1049-477B-A894-13FCB96C45DE} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC0FA8D3-6449-4FDA-BB46-ECF58FAD23B4} diff --git a/src/samples/WorkflowCore.Sample20/ActivityWorkflow.cs b/src/samples/WorkflowCore.Sample20/ActivityWorkflow.cs deleted file mode 100644 index 03208dcfd..000000000 --- a/src/samples/WorkflowCore.Sample20/ActivityWorkflow.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using WorkflowCore.Interface; -using WorkflowCore.Sample20.Steps; - -namespace WorkflowCore.Sample20 -{ - class ActivityWorkflow : IWorkflow - { - public string Id => "activity-sample"; - public int Version => 1; - - public void Build(IWorkflowBuilder builder) - { - builder - .StartWith() - .Activity((data, context) => "get-approval-" + context.Workflow.Id, (data) => data.Request) - .Output(data => data.ApprovedBy, step => step.Result) - .Then() - .Input(step => step.Message, data => "Approved by " + data.ApprovedBy) - .Then(); - } - } - - class MyData - { - public string Request { get; set; } - public string ApprovedBy { get; set; } - } -} diff --git a/src/samples/WorkflowCore.Sample20/Program.cs b/src/samples/WorkflowCore.Sample20/Program.cs deleted file mode 100644 index 4e8f1303f..000000000 --- a/src/samples/WorkflowCore.Sample20/Program.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using System; -using WorkflowCore.Interface; - -namespace WorkflowCore.Sample20 -{ - class Program - { - static void Main(string[] args) - { - // THE TEST DISABLED FOR THE BUILD TIME LIMIT - /*var serviceProvider = ConfigureServices(); - - //start the workflow host - var host = serviceProvider.GetService(); - host.RegisterWorkflow(); - host.Start(); - - Console.WriteLine("Starting workflow..."); - - var workflowId = host.StartWorkflow("activity-sample", new MyData { Request = "Spend $1,000,000" }).Result; - - var approval = host.GetPendingActivity("get-approval-" + workflowId, "worker1", TimeSpan.FromMinutes(1)).Result; - - if (approval != null) - { - Console.WriteLine("Approval required for " + approval.Parameters); - host.SubmitActivitySuccess(approval.Token, "John Smith"); - } - - Console.ReadLine(); - host.Stop();*/ - } - - private static IServiceProvider ConfigureServices() - { - //setup dependency injection - IServiceCollection services = new ServiceCollection(); - //services.AddWorkflow(); - services.AddWorkflow(x => x.UseMongoDB(@"mongodb://localhost:27017", "workflow")); - //services.AddWorkflow(x => x.UseSqlServer(@"Server=.;Database=WorkflowCore;Trusted_Connection=True;", true, true)); - //services.AddWorkflow(x => x.UsePostgreSQL(@"Server=127.0.0.1;Port=5432;Database=workflow;User Id=postgres;", true, true)); - services.AddLogging(cfg => - { - cfg.AddConsole(); - cfg.AddDebug(); - }); - - var serviceProvider = services.BuildServiceProvider(); - return serviceProvider; - } - } -} diff --git a/src/samples/WorkflowCore.Sample20/README.md b/src/samples/WorkflowCore.Sample20/README.md deleted file mode 100644 index 46f5d1e22..000000000 --- a/src/samples/WorkflowCore.Sample20/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# Activity sample - -Illustrates how to have your workflow wait for an external activity that is fulfilled by a worker that you implement. - -This workflow will wait for the `get-approval-{workflowId}` activity and pass the request string to it as an input. - -The main reason behind of this example is Activities are global listeners. Therefore, in some cases, you want to be sure about its uniqueness. - -Also, you can take look the issue https://github.com/danielgerlag/workflow-core/issues/542 - -```c# -builder - .StartWith() - .Activity((data, context) => context.Workflow.Id, (data) => data.Request) - .Output(data => data.ApprovedBy, step => step.Result) - .Then() - .Input(step => step.Message, data => "Approved by " + data.ApprovedBy) - .Then(); -``` - -Then we implement an activity worker to pull pending activities of type `get-approval`, where we can inspect the input and submit a response back to the waiting workflow. - -```c# -var workflowId = host.StartWorkflow("activity-sample", new MyData { Request = "Spend $1,000,000" }).Result; - -var approval = host.GetPendingActivity("get-approval-" + workflowId, "worker1", TimeSpan.FromMinutes(1)).Result; - -if (approval != null) -{ - Console.WriteLine("Approval required for " + approval.Parameters); - host.SubmitActivitySuccess(approval.Token, "John Smith"); -} -``` - diff --git a/src/samples/WorkflowCore.Sample20/Steps/CustomMessage.cs b/src/samples/WorkflowCore.Sample20/Steps/CustomMessage.cs deleted file mode 100644 index cad8eff61..000000000 --- a/src/samples/WorkflowCore.Sample20/Steps/CustomMessage.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Linq; -using WorkflowCore.Interface; -using WorkflowCore.Models; - -namespace WorkflowCore.Sample20.Steps -{ - public class CustomMessage : StepBody - { - - public string Message { get; set; } - - public override ExecutionResult Run(IStepExecutionContext context) - { - Console.WriteLine(Message); - return ExecutionResult.Next(); - } - } -} diff --git a/src/samples/WorkflowCore.Sample20/Steps/GoodbyeWorld.cs b/src/samples/WorkflowCore.Sample20/Steps/GoodbyeWorld.cs deleted file mode 100644 index 0908966d9..000000000 --- a/src/samples/WorkflowCore.Sample20/Steps/GoodbyeWorld.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Linq; -using WorkflowCore.Interface; -using WorkflowCore.Models; - -namespace WorkflowCore.Sample20.Steps -{ - public class GoodbyeWorld : StepBody - { - public override ExecutionResult Run(IStepExecutionContext context) - { - Console.WriteLine("Goodbye world"); - return ExecutionResult.Next(); - } - } -} diff --git a/src/samples/WorkflowCore.Sample20/Steps/HelloWorld.cs b/src/samples/WorkflowCore.Sample20/Steps/HelloWorld.cs deleted file mode 100644 index 5623bf684..000000000 --- a/src/samples/WorkflowCore.Sample20/Steps/HelloWorld.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Linq; -using WorkflowCore.Interface; -using WorkflowCore.Models; - -namespace WorkflowCore.Sample20.Steps -{ - public class HelloWorld : StepBody - { - public override ExecutionResult Run(IStepExecutionContext context) - { - Console.WriteLine("Hello world"); - return ExecutionResult.Next(); - } - } -} diff --git a/src/samples/WorkflowCore.Sample20/WorkflowCore.Sample20.csproj b/src/samples/WorkflowCore.Sample20/WorkflowCore.Sample20.csproj deleted file mode 100644 index 660b47511..000000000 --- a/src/samples/WorkflowCore.Sample20/WorkflowCore.Sample20.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - Exe - netcoreapp3.0 - - - - - - - - - - - - - - - From 19c34cbe376f92737a18547b448a5959d889e129 Mon Sep 17 00:00:00 2001 From: lyzerk Date: Mon, 2 Aug 2021 08:32:16 +0300 Subject: [PATCH 156/342] sln fix --- WorkflowCore.sln | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WorkflowCore.sln b/WorkflowCore.sln index de509ed05..be18fd721 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -150,7 +150,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Tests.QueuePro EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample19", "src\samples\WorkflowCore.Sample19\WorkflowCore.Sample19.csproj", "{1223ED47-3E5E-4960-B70D-DFAF550F6666}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Persistence.RavenDB", "src\providers\WorkflowCore.Persistence.RavenDB\WorkflowCore.Persistence.RavenDB.csproj", "{AF205715-C8B7-42EF-BF14-AFC9E7F27242}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowCore.Persistence.RavenDB", "src\providers\WorkflowCore.Persistence.RavenDB\WorkflowCore.Persistence.RavenDB.csproj", "{AF205715-C8B7-42EF-BF14-AFC9E7F27242}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution From 078acc07e8d785aebf283d119a3cbd49b1013195 Mon Sep 17 00:00:00 2001 From: lyzerk Date: Mon, 2 Aug 2021 08:51:37 +0300 Subject: [PATCH 157/342] disable activity scenario2 --- .../Scenarios/ActivityScenario2.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario2.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario2.cs index 356f77402..1cf5b6330 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario2.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario2.cs @@ -8,6 +8,8 @@ namespace WorkflowCore.IntegrationTests.Scenarios { + /* + * DISABLED for bug on build pipeline public class ActivityScenario2 : WorkflowTest { public class MyDataClass @@ -71,5 +73,6 @@ public void Scenario() outData.Value1.Should().Be("a1"); outData.Value2.Should().Be(2); } - } + }*/ + } From f3042be3df9a3b032d6feed1fd60ba90db0328cf Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Mon, 2 Aug 2021 11:16:11 -0700 Subject: [PATCH 158/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index a02261928..fa0f334be 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.5.2 - 3.5.2.0 - 3.5.2.0 + 3.5.3 + 3.5.3.0 + 3.5.3.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.5.2 + 3.5.3 From cd9b0961cf96733a5851fa92a5b0114bca6a5f55 Mon Sep 17 00:00:00 2001 From: JRoger Date: Tue, 3 Aug 2021 09:38:07 +0800 Subject: [PATCH 159/342] feat: Compatible with net5.0 --- .github/workflows/dotnet.yml | 2 +- .../WorkflowCore.Persistence.MySQL/MysqlContext.cs | 4 ++++ .../WorkflowCore.Persistence.MySQL.csproj | 12 ++++++++++-- .../WorkflowCore.Sample04.csproj | 14 +++++++------- test/WorkflowCore.Tests.MySQL/DockerSetup.cs | 4 ++-- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 29100399e..12b398572 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -16,7 +16,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: 3.1.301 + dotnet-version: 5.0.* - name: Restore dependencies run: dotnet restore - name: Build diff --git a/src/providers/WorkflowCore.Persistence.MySQL/MysqlContext.cs b/src/providers/WorkflowCore.Persistence.MySQL/MysqlContext.cs index dbf4a8085..a6ebba9c2 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/MysqlContext.cs +++ b/src/providers/WorkflowCore.Persistence.MySQL/MysqlContext.cs @@ -21,7 +21,11 @@ public MysqlContext(string connectionString, Action builder) diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index af6cbc18d..e0e83315b 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -4,7 +4,7 @@ Workflow Core MySQL Persistence Provider 1.0.0 Daniel Gerlag - netstandard2.0 + netstandard2.0;netstandard2.1 WorkflowCore.Persistence.MySQL WorkflowCore.Persistence.MySQL workflow;.NET;Core;state machine;WorkflowCore;MySQL @@ -18,7 +18,7 @@ Provides support to persist workflows running on Workflow Core to a MySQL database. - + all runtime; build; native; contentfiles; analyzers @@ -26,6 +26,14 @@ + + + all + runtime; build; native; contentfiles; analyzers + + + + diff --git a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj index 96f0355c0..ddae958be 100644 --- a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj +++ b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj @@ -4,7 +4,7 @@ netcoreapp3.1 WorkflowCore.Sample04 Exe - WorkflowCore.Sample04 + WorkflowCore.Sample04 false false false @@ -25,16 +25,16 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/WorkflowCore.Tests.MySQL/DockerSetup.cs b/test/WorkflowCore.Tests.MySQL/DockerSetup.cs index f91909f9d..05758f4c1 100644 --- a/test/WorkflowCore.Tests.MySQL/DockerSetup.cs +++ b/test/WorkflowCore.Tests.MySQL/DockerSetup.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using Docker.Testify; using Xunit; -using MySql.Data.MySqlClient; using System; +using MySqlConnector; namespace WorkflowCore.Tests.MySQL { @@ -13,7 +13,7 @@ public class MysqlDockerSetup : DockerSetup public static string RootPassword => "rootpwd123"; public override TimeSpan TimeOut => TimeSpan.FromSeconds(60); - + public override string ImageName => "mysql"; public override IList EnvironmentVariables => new List { $"MYSQL_ROOT_PASSWORD={RootPassword}" From a38721861e408aae2a9f618e221e6c65619ee223 Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Tue, 3 Aug 2021 12:43:16 +0300 Subject: [PATCH 160/342] Fix parallel events test --- .../Scenarios/ParallelEventsScenario.cs | 71 ++++++++++--------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ParallelEventsScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ParallelEventsScenario.cs index d7176c880..2c3b6825f 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/ParallelEventsScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ParallelEventsScenario.cs @@ -4,7 +4,8 @@ using Xunit; using FluentAssertions; using WorkflowCore.Testing; -using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; namespace WorkflowCore.IntegrationTests.Scenarios { @@ -19,9 +20,21 @@ public class MyDataClass public string StrValue2 { get; set; } } + public class SomeTask : StepBodyAsync + { + public TimeSpan Delay { get; set; } + + public override async Task RunAsync(IStepExecutionContext context) + { + await Task.Delay(Delay); + + return ExecutionResult.Next(); + } + } + public class ParallelEventsWorkflow : IWorkflow { - public string Id => "EventWorkflow"; + public string Id => nameof(ParallelEventsScenario); public int Version => 1; public void Build(IWorkflowBuilder builder) { @@ -29,35 +42,20 @@ public void Build(IWorkflowBuilder builder) .StartWith(context => ExecutionResult.Next()) .Parallel() .Do(then => - then.WaitFor("Event1", data => EVENT_KEY).Then(x => - { - Thread.Sleep(300); - return ExecutionResult.Next(); - })) + then.WaitFor("Event1", data => EVENT_KEY).Then() + .Input(step => step.Delay, data => TimeSpan.FromMilliseconds(2000))) .Do(then => - then.WaitFor("Event2", data => EVENT_KEY).Then(x => - { - Thread.Sleep(100); - return ExecutionResult.Next(); - })) + then.WaitFor("Event2", data => EVENT_KEY).Then() + .Input(step => step.Delay, data => TimeSpan.FromMilliseconds(2000))) .Do(then => - then.WaitFor("Event3", data => EVENT_KEY).Then(x => - { - Thread.Sleep(1000); - return ExecutionResult.Next(); - })) + then.WaitFor("Event3", data => EVENT_KEY).Then() + .Input(step => step.Delay, data => TimeSpan.FromMilliseconds(5000))) .Do(then => - then.WaitFor("Event4", data => EVENT_KEY).Then(x => - { - Thread.Sleep(100); - return ExecutionResult.Next(); - })) + then.WaitFor("Event4", data => EVENT_KEY).Then() + .Input(step => step.Delay, data => TimeSpan.FromMilliseconds(100))) .Do(then => - then.WaitFor("Event5", data => EVENT_KEY).Then(x => - { - Thread.Sleep(100); - return ExecutionResult.Next(); - })) + then.WaitFor("Event5", data => EVENT_KEY).Then() + .Input(step => step.Delay, data => TimeSpan.FromMilliseconds(100))) .Join() .Then(x => { @@ -71,16 +69,21 @@ public ParallelEventsScenario() Setup(); } + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(s => s.UsePollInterval(TimeSpan.FromSeconds(1))); + } + [Fact] - public void Scenario() + public async Task Scenario() { var eventKey = Guid.NewGuid().ToString(); - var workflowId = StartWorkflow(new MyDataClass { StrValue1 = eventKey, StrValue2 = eventKey }); - Host.PublishEvent("Event1", EVENT_KEY, "Pass1"); - Host.PublishEvent("Event2", EVENT_KEY, "Pass2"); - Host.PublishEvent("Event3", EVENT_KEY, "Pass3"); - Host.PublishEvent("Event4", EVENT_KEY, "Pass4"); - Host.PublishEvent("Event5", EVENT_KEY, "Pass5"); + var workflowId = await StartWorkflowAsync(new MyDataClass { StrValue1 = eventKey, StrValue2 = eventKey }); + await Host.PublishEvent("Event1", EVENT_KEY, "Pass1"); + await Host.PublishEvent("Event2", EVENT_KEY, "Pass2"); + await Host.PublishEvent("Event3", EVENT_KEY, "Pass3"); + await Host.PublishEvent("Event4", EVENT_KEY, "Pass4"); + await Host.PublishEvent("Event5", EVENT_KEY, "Pass5"); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); From b43785b03acede2a670541298edd805e0e461e6d Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Tue, 3 Aug 2021 18:50:25 +0300 Subject: [PATCH 161/342] Allow to disable events publisher --- src/WorkflowCore/Models/WorkflowOptions.cs | 1 + src/WorkflowCore/ServiceCollectionExtensions.cs | 13 ++++++++++--- .../Services/ErrorHandlers/CompensateHandler.cs | 4 +--- .../Services/ErrorHandlers/SuspendHandler.cs | 2 +- .../Services/ErrorHandlers/TerminateHandler.cs | 2 +- .../Services/ExecutionResultProcessor.cs | 4 ++-- src/WorkflowCore/Services/WorkflowExecutor.cs | 4 ++-- 7 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/WorkflowCore/Models/WorkflowOptions.cs b/src/WorkflowCore/Models/WorkflowOptions.cs index bf2d28e06..fb1ae9a7e 100644 --- a/src/WorkflowCore/Models/WorkflowOptions.cs +++ b/src/WorkflowCore/Models/WorkflowOptions.cs @@ -38,6 +38,7 @@ public WorkflowOptions(IServiceCollection services) public bool EnableEvents { get; set; } = true; public bool EnableIndexes { get; set; } = true; public bool EnablePolling { get; set; } = true; + public bool EnableLifeCycleEventsPublisher { get; set; } = true; public void UsePersistence(Func factory) { diff --git a/src/WorkflowCore/ServiceCollectionExtensions.cs b/src/WorkflowCore/ServiceCollectionExtensions.cs index 760a89d41..3ba7de642 100644 --- a/src/WorkflowCore/ServiceCollectionExtensions.cs +++ b/src/WorkflowCore/ServiceCollectionExtensions.cs @@ -31,7 +31,16 @@ public static IServiceCollection AddWorkflow(this IServiceCollection services, A services.AddSingleton(); services.AddSingleton(options); - services.AddSingleton(); + + if (options.EnableLifeCycleEventsPublisher) + { + services.AddSingleton(); + services.AddTransient(sp => sp.GetService()); + } + else + { + services.AddTransient(provider => null); + } if (options.EnableWorkflows) { @@ -53,8 +62,6 @@ public static IServiceCollection AddWorkflow(this IServiceCollection services, A services.AddTransient(); } - services.AddTransient(sp => sp.GetService()); - services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs index 028f0d112..d8990c160 100644 --- a/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs @@ -8,17 +8,15 @@ namespace WorkflowCore.Services.ErrorHandlers { public class CompensateHandler : IWorkflowErrorHandler { - private readonly ILifeCycleEventPublisher _eventPublisher; private readonly IExecutionPointerFactory _pointerFactory; private readonly IDateTimeProvider _datetimeProvider; private readonly WorkflowOptions _options; public WorkflowErrorHandling Type => WorkflowErrorHandling.Compensate; - public CompensateHandler(IExecutionPointerFactory pointerFactory, ILifeCycleEventPublisher eventPublisher, IDateTimeProvider datetimeProvider, WorkflowOptions options) + public CompensateHandler(IExecutionPointerFactory pointerFactory, IDateTimeProvider datetimeProvider, WorkflowOptions options) { _pointerFactory = pointerFactory; - _eventPublisher = eventPublisher; _datetimeProvider = datetimeProvider; _options = options; } diff --git a/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs index 3cc3279ec..8ff8fa35b 100755 --- a/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs @@ -21,7 +21,7 @@ public SuspendHandler(ILifeCycleEventPublisher eventPublisher, IDateTimeProvider public void Handle(WorkflowInstance workflow, WorkflowDefinition def, ExecutionPointer pointer, WorkflowStep step, Exception exception, Queue bubbleUpQueue) { workflow.Status = WorkflowStatus.Suspended; - _eventPublisher.PublishNotification(new WorkflowSuspended + _eventPublisher?.PublishNotification(new WorkflowSuspended { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, diff --git a/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs index 6cafe5ece..a3cc566fd 100755 --- a/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs @@ -23,7 +23,7 @@ public void Handle(WorkflowInstance workflow, WorkflowDefinition def, ExecutionP workflow.Status = WorkflowStatus.Terminated; workflow.CompleteTime = _dateTimeProvider.UtcNow; - _eventPublisher.PublishNotification(new WorkflowTerminated + _eventPublisher?.PublishNotification(new WorkflowTerminated { EventTimeUtc = _dateTimeProvider.UtcNow, Reference = workflow.Reference, diff --git a/src/WorkflowCore/Services/ExecutionResultProcessor.cs b/src/WorkflowCore/Services/ExecutionResultProcessor.cs index 3c684945f..89f21f074 100755 --- a/src/WorkflowCore/Services/ExecutionResultProcessor.cs +++ b/src/WorkflowCore/Services/ExecutionResultProcessor.cs @@ -77,7 +77,7 @@ public void ProcessExecutionResult(WorkflowInstance workflow, WorkflowDefinition subsequent.Active = true; } - _eventPublisher.PublishNotification(new StepCompleted + _eventPublisher?.PublishNotification(new StepCompleted { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, @@ -102,7 +102,7 @@ public void ProcessExecutionResult(WorkflowInstance workflow, WorkflowDefinition public void HandleStepException(WorkflowInstance workflow, WorkflowDefinition def, ExecutionPointer pointer, WorkflowStep step, Exception exception) { - _eventPublisher.PublishNotification(new WorkflowError + _eventPublisher?.PublishNotification(new WorkflowError { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index ebdc818fe..8fa0101a0 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -123,7 +123,7 @@ private bool InitializeStep(WorkflowInstance workflow, WorkflowStep step, Workfl if (pointer.Status != PointerStatus.Running) { pointer.Status = PointerStatus.Running; - _publisher.PublishNotification(new StepStarted + _publisher?.PublishNotification(new StepStarted { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, @@ -264,7 +264,7 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo await middlewareRunner.RunPostMiddleware(workflow, def); } - _publisher.PublishNotification(new WorkflowCompleted + _publisher?.PublishNotification(new WorkflowCompleted { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, From 48ba0e0253d5210610f62f4a27db31c2dd494d86 Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Tue, 10 Aug 2021 11:03:02 +0300 Subject: [PATCH 162/342] Revert "Allow to disable events publisher" This reverts commit b43785b03acede2a670541298edd805e0e461e6d. --- src/WorkflowCore/Models/WorkflowOptions.cs | 1 - src/WorkflowCore/ServiceCollectionExtensions.cs | 13 +++---------- .../Services/ErrorHandlers/CompensateHandler.cs | 4 +++- .../Services/ErrorHandlers/SuspendHandler.cs | 2 +- .../Services/ErrorHandlers/TerminateHandler.cs | 2 +- .../Services/ExecutionResultProcessor.cs | 4 ++-- src/WorkflowCore/Services/WorkflowExecutor.cs | 4 ++-- 7 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/WorkflowCore/Models/WorkflowOptions.cs b/src/WorkflowCore/Models/WorkflowOptions.cs index fb1ae9a7e..bf2d28e06 100644 --- a/src/WorkflowCore/Models/WorkflowOptions.cs +++ b/src/WorkflowCore/Models/WorkflowOptions.cs @@ -38,7 +38,6 @@ public WorkflowOptions(IServiceCollection services) public bool EnableEvents { get; set; } = true; public bool EnableIndexes { get; set; } = true; public bool EnablePolling { get; set; } = true; - public bool EnableLifeCycleEventsPublisher { get; set; } = true; public void UsePersistence(Func factory) { diff --git a/src/WorkflowCore/ServiceCollectionExtensions.cs b/src/WorkflowCore/ServiceCollectionExtensions.cs index 3ba7de642..760a89d41 100644 --- a/src/WorkflowCore/ServiceCollectionExtensions.cs +++ b/src/WorkflowCore/ServiceCollectionExtensions.cs @@ -31,16 +31,7 @@ public static IServiceCollection AddWorkflow(this IServiceCollection services, A services.AddSingleton(); services.AddSingleton(options); - - if (options.EnableLifeCycleEventsPublisher) - { - services.AddSingleton(); - services.AddTransient(sp => sp.GetService()); - } - else - { - services.AddTransient(provider => null); - } + services.AddSingleton(); if (options.EnableWorkflows) { @@ -62,6 +53,8 @@ public static IServiceCollection AddWorkflow(this IServiceCollection services, A services.AddTransient(); } + services.AddTransient(sp => sp.GetService()); + services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs index d8990c160..028f0d112 100644 --- a/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs @@ -8,15 +8,17 @@ namespace WorkflowCore.Services.ErrorHandlers { public class CompensateHandler : IWorkflowErrorHandler { + private readonly ILifeCycleEventPublisher _eventPublisher; private readonly IExecutionPointerFactory _pointerFactory; private readonly IDateTimeProvider _datetimeProvider; private readonly WorkflowOptions _options; public WorkflowErrorHandling Type => WorkflowErrorHandling.Compensate; - public CompensateHandler(IExecutionPointerFactory pointerFactory, IDateTimeProvider datetimeProvider, WorkflowOptions options) + public CompensateHandler(IExecutionPointerFactory pointerFactory, ILifeCycleEventPublisher eventPublisher, IDateTimeProvider datetimeProvider, WorkflowOptions options) { _pointerFactory = pointerFactory; + _eventPublisher = eventPublisher; _datetimeProvider = datetimeProvider; _options = options; } diff --git a/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs index 8ff8fa35b..3cc3279ec 100755 --- a/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/SuspendHandler.cs @@ -21,7 +21,7 @@ public SuspendHandler(ILifeCycleEventPublisher eventPublisher, IDateTimeProvider public void Handle(WorkflowInstance workflow, WorkflowDefinition def, ExecutionPointer pointer, WorkflowStep step, Exception exception, Queue bubbleUpQueue) { workflow.Status = WorkflowStatus.Suspended; - _eventPublisher?.PublishNotification(new WorkflowSuspended + _eventPublisher.PublishNotification(new WorkflowSuspended { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, diff --git a/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs index a3cc566fd..6cafe5ece 100755 --- a/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/TerminateHandler.cs @@ -23,7 +23,7 @@ public void Handle(WorkflowInstance workflow, WorkflowDefinition def, ExecutionP workflow.Status = WorkflowStatus.Terminated; workflow.CompleteTime = _dateTimeProvider.UtcNow; - _eventPublisher?.PublishNotification(new WorkflowTerminated + _eventPublisher.PublishNotification(new WorkflowTerminated { EventTimeUtc = _dateTimeProvider.UtcNow, Reference = workflow.Reference, diff --git a/src/WorkflowCore/Services/ExecutionResultProcessor.cs b/src/WorkflowCore/Services/ExecutionResultProcessor.cs index 89f21f074..3c684945f 100755 --- a/src/WorkflowCore/Services/ExecutionResultProcessor.cs +++ b/src/WorkflowCore/Services/ExecutionResultProcessor.cs @@ -77,7 +77,7 @@ public void ProcessExecutionResult(WorkflowInstance workflow, WorkflowDefinition subsequent.Active = true; } - _eventPublisher?.PublishNotification(new StepCompleted + _eventPublisher.PublishNotification(new StepCompleted { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, @@ -102,7 +102,7 @@ public void ProcessExecutionResult(WorkflowInstance workflow, WorkflowDefinition public void HandleStepException(WorkflowInstance workflow, WorkflowDefinition def, ExecutionPointer pointer, WorkflowStep step, Exception exception) { - _eventPublisher?.PublishNotification(new WorkflowError + _eventPublisher.PublishNotification(new WorkflowError { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index 8fa0101a0..ebdc818fe 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -123,7 +123,7 @@ private bool InitializeStep(WorkflowInstance workflow, WorkflowStep step, Workfl if (pointer.Status != PointerStatus.Running) { pointer.Status = PointerStatus.Running; - _publisher?.PublishNotification(new StepStarted + _publisher.PublishNotification(new StepStarted { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, @@ -264,7 +264,7 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo await middlewareRunner.RunPostMiddleware(workflow, def); } - _publisher?.PublishNotification(new WorkflowCompleted + _publisher.PublishNotification(new WorkflowCompleted { EventTimeUtc = _datetimeProvider.UtcNow, Reference = workflow.Reference, From 133a7feac08e7a0cc4d6bd61d717429e01c9b7cd Mon Sep 17 00:00:00 2001 From: Viktor Kryzhanovskyi Date: Tue, 10 Aug 2021 12:04:07 +0300 Subject: [PATCH 163/342] Changes after code review from Daniel --- src/WorkflowCore/Models/WorkflowOptions.cs | 1 + .../ErrorHandlers/CompensateHandler.cs | 4 +- .../Services/LifeCycleEventPublisher.cs | 7 ++- .../Services/LifeCycleEventPublisherTests.cs | 49 +++++++++++++++++-- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/WorkflowCore/Models/WorkflowOptions.cs b/src/WorkflowCore/Models/WorkflowOptions.cs index bf2d28e06..fb1ae9a7e 100644 --- a/src/WorkflowCore/Models/WorkflowOptions.cs +++ b/src/WorkflowCore/Models/WorkflowOptions.cs @@ -38,6 +38,7 @@ public WorkflowOptions(IServiceCollection services) public bool EnableEvents { get; set; } = true; public bool EnableIndexes { get; set; } = true; public bool EnablePolling { get; set; } = true; + public bool EnableLifeCycleEventsPublisher { get; set; } = true; public void UsePersistence(Func factory) { diff --git a/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs b/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs index 028f0d112..d8990c160 100644 --- a/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs +++ b/src/WorkflowCore/Services/ErrorHandlers/CompensateHandler.cs @@ -8,17 +8,15 @@ namespace WorkflowCore.Services.ErrorHandlers { public class CompensateHandler : IWorkflowErrorHandler { - private readonly ILifeCycleEventPublisher _eventPublisher; private readonly IExecutionPointerFactory _pointerFactory; private readonly IDateTimeProvider _datetimeProvider; private readonly WorkflowOptions _options; public WorkflowErrorHandling Type => WorkflowErrorHandling.Compensate; - public CompensateHandler(IExecutionPointerFactory pointerFactory, ILifeCycleEventPublisher eventPublisher, IDateTimeProvider datetimeProvider, WorkflowOptions options) + public CompensateHandler(IExecutionPointerFactory pointerFactory, IDateTimeProvider datetimeProvider, WorkflowOptions options) { _pointerFactory = pointerFactory; - _eventPublisher = eventPublisher; _datetimeProvider = datetimeProvider; _options = options; } diff --git a/src/WorkflowCore/Services/LifeCycleEventPublisher.cs b/src/WorkflowCore/Services/LifeCycleEventPublisher.cs index 1dce43e4c..e73c6bf4f 100644 --- a/src/WorkflowCore/Services/LifeCycleEventPublisher.cs +++ b/src/WorkflowCore/Services/LifeCycleEventPublisher.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Threading.Tasks; using WorkflowCore.Interface; +using WorkflowCore.Models; using WorkflowCore.Models.LifeCycleEvents; namespace WorkflowCore.Services @@ -10,20 +11,22 @@ namespace WorkflowCore.Services public class LifeCycleEventPublisher : ILifeCycleEventPublisher, IDisposable { private readonly ILifeCycleEventHub _eventHub; + private readonly WorkflowOptions _workflowOptions; private readonly ILogger _logger; private BlockingCollection _outbox; private Task _dispatchTask; - public LifeCycleEventPublisher(ILifeCycleEventHub eventHub, ILoggerFactory loggerFactory) + public LifeCycleEventPublisher(ILifeCycleEventHub eventHub, WorkflowOptions workflowOptions, ILoggerFactory loggerFactory) { _eventHub = eventHub; + _workflowOptions = workflowOptions; _outbox = new BlockingCollection(); _logger = loggerFactory.CreateLogger(GetType()); } public void PublishNotification(LifeCycleEvent evt) { - if (_outbox.IsAddingCompleted) + if (_outbox.IsAddingCompleted || !_workflowOptions.EnableLifeCycleEventsPublisher) return; _outbox.Add(evt); diff --git a/test/WorkflowCore.UnitTests/Services/LifeCycleEventPublisherTests.cs b/test/WorkflowCore.UnitTests/Services/LifeCycleEventPublisherTests.cs index bfee3ad07..d8e38437e 100644 --- a/test/WorkflowCore.UnitTests/Services/LifeCycleEventPublisherTests.cs +++ b/test/WorkflowCore.UnitTests/Services/LifeCycleEventPublisherTests.cs @@ -1,8 +1,9 @@ -using System; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Moq; using WorkflowCore.Interface; +using WorkflowCore.Models; using WorkflowCore.Models.LifeCycleEvents; using WorkflowCore.Services; using Xunit; @@ -17,10 +18,17 @@ public async Task PublishNotification_WhenStarted_PublishesNotification() // Arrange var wasCalled = new TaskCompletionSource(); var eventHubMock = new Mock(); + var serviceCollectionMock = new Mock(); + + var workflowOptions = new WorkflowOptions(serviceCollectionMock.Object) + { + EnableLifeCycleEventsPublisher = true + }; + eventHubMock .Setup(hub => hub.PublishNotification(It.IsAny())) .Callback(() => wasCalled.SetResult(true)); - LifeCycleEventPublisher publisher = new LifeCycleEventPublisher(eventHubMock.Object, new LoggerFactory()); + LifeCycleEventPublisher publisher = new LifeCycleEventPublisher(eventHubMock.Object, workflowOptions, new LoggerFactory()); // Act publisher.Start(); @@ -28,6 +36,7 @@ public async Task PublishNotification_WhenStarted_PublishesNotification() // Assert await wasCalled.Task; + eventHubMock.Verify(hub => hub.PublishNotification(It.IsAny()), Times.Once()); } [Fact(DisplayName = "Notifications should be published when the publisher is running")] @@ -36,10 +45,17 @@ public async Task PublishNotification_WhenRestarted_PublishesNotification() // Arrange var wasCalled = new TaskCompletionSource(); var eventHubMock = new Mock(); + var serviceCollectionMock = new Mock(); + + var workflowOptions = new WorkflowOptions(serviceCollectionMock.Object) + { + EnableLifeCycleEventsPublisher = true + }; + eventHubMock .Setup(hub => hub.PublishNotification(It.IsAny())) .Callback(() => wasCalled.SetResult(true)); - LifeCycleEventPublisher publisher = new LifeCycleEventPublisher(eventHubMock.Object, new LoggerFactory()); + LifeCycleEventPublisher publisher = new LifeCycleEventPublisher(eventHubMock.Object, workflowOptions, new LoggerFactory()); // Act publisher.Start(); @@ -49,6 +65,33 @@ public async Task PublishNotification_WhenRestarted_PublishesNotification() // Assert await wasCalled.Task; + eventHubMock.Verify(hub => hub.PublishNotification(It.IsAny()), Times.Once()); + } + + [Fact(DisplayName = "Notifications should be disabled if option EnableLifeCycleEventsPublisher is disabled")] + public void PublishNotification_Disabled() + { + // Arrange + var eventHubMock = new Mock(); + var serviceCollectionMock = new Mock(); + + var workflowOptions = new WorkflowOptions(serviceCollectionMock.Object) + { + EnableLifeCycleEventsPublisher = false + }; + + eventHubMock + .Setup(hub => hub.PublishNotification(It.IsAny())) + .Returns(Task.CompletedTask); + LifeCycleEventPublisher publisher = new LifeCycleEventPublisher(eventHubMock.Object, workflowOptions, new LoggerFactory()); + + // Act + publisher.Start(); + publisher.PublishNotification(new StepCompleted()); + publisher.Stop(); + + // Assert + eventHubMock.Verify(hub => hub.PublishNotification(It.IsAny()), Times.Never()); } } } \ No newline at end of file From a6c84081ba577839cc17965246de1fc87458a11d Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 17 Aug 2021 07:25:24 -0700 Subject: [PATCH 164/342] Update Directory.Build.props --- src/Directory.Build.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index fa0f334be..13d001297 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -5,9 +5,9 @@ git https://github.com/danielgerlag/workflow-core.git 3.5.3 - 3.5.3.0 - 3.5.3.0 + 3.5.4.0 + 3.5.4.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.5.3 + 3.5.4 From 0ba1b75d934b8b8e0e53599b6ff66e5031205ba4 Mon Sep 17 00:00:00 2001 From: Uladzimir Kavaliuk Date: Tue, 17 Aug 2021 19:05:29 +0300 Subject: [PATCH 165/342] Fix issue 894 Added check whether collection is empty. Added specific test scenario. --- src/WorkflowCore/Primitives/Foreach.cs | 7 ++++- .../Scenarios/ForeachScenario.cs | 29 +++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/WorkflowCore/Primitives/Foreach.cs b/src/WorkflowCore/Primitives/Foreach.cs index 1a64ddfdb..ef4c39fe0 100644 --- a/src/WorkflowCore/Primitives/Foreach.cs +++ b/src/WorkflowCore/Primitives/Foreach.cs @@ -15,7 +15,12 @@ public override ExecutionResult Run(IStepExecutionContext context) { if (context.PersistenceData == null) { - var values = Collection.Cast(); + var values = Collection.Cast().ToList(); + if (!values.Any()) + { + return ExecutionResult.Next(); + } + if (RunParallel) { return ExecutionResult.Branch(new List(values), new IteratorPersistenceData { ChildrenActive = true }); diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ForeachScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ForeachScenario.cs index fb0747d5e..774064b8b 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/ForeachScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ForeachScenario.cs @@ -18,7 +18,6 @@ public class ForeachScenario : WorkflowTest Numbers { get; set; } = new List(); + + public bool IsParallel { get; set; } = true; } public class ForeachWorkflow : IWorkflow @@ -43,7 +45,7 @@ public void Build(IWorkflowBuilder builder) Step1Ticker++; return ExecutionResult.Next(); }) - .ForEach(x => new List { 2, 2, 3 }) + .ForEach(x => x.Numbers, x => x.IsParallel) .Do(x => x.StartWith()) .Then(context => { @@ -57,12 +59,18 @@ public void Build(IWorkflowBuilder builder) public ForeachScenario() { Setup(); + + Step1Ticker = 0; + Step2Ticker = 0; + Step3Ticker = 0; + AfterLoopValue = 0; + CheckSum = 0; } [Fact] public void Scenario() { - var workflowId = StartWorkflow(null); + var workflowId = StartWorkflow(new MyDataClass { Numbers = new List { 2, 2, 3 } }); WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); Step1Ticker.Should().Be(1); @@ -73,5 +81,20 @@ public void Scenario() GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); UnhandledStepErrors.Count.Should().Be(0); } + + [Fact] + public void EmptyCollectionSequentialScenario() + { + var workflowId = StartWorkflow(new MyDataClass { IsParallel = false }); + WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); + + GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); + UnhandledStepErrors.Count.Should().Be(0); + Step1Ticker.Should().Be(1); + Step2Ticker.Should().Be(0); + Step3Ticker.Should().Be(1); + AfterLoopValue.Should().Be(0); + CheckSum.Should().Be(0); + } } } From 1efecabf70e36cd6fe6654f8aacc0eb431b3dc76 Mon Sep 17 00:00:00 2001 From: glucaci Date: Mon, 23 Aug 2021 15:00:26 +0200 Subject: [PATCH 166/342] Cleanup --- src/WorkflowCore/Interface/Persistence/ITransaction.cs | 10 ---------- src/WorkflowCore/Services/WorkflowController.cs | 4 ++-- .../Services/MongoPersistenceProvider.cs | 1 - 3 files changed, 2 insertions(+), 13 deletions(-) delete mode 100644 src/WorkflowCore/Interface/Persistence/ITransaction.cs diff --git a/src/WorkflowCore/Interface/Persistence/ITransaction.cs b/src/WorkflowCore/Interface/Persistence/ITransaction.cs deleted file mode 100644 index cbb51e778..000000000 --- a/src/WorkflowCore/Interface/Persistence/ITransaction.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace WorkflowCore.Interface -{ - public interface ITransaction - { - /// - /// The transaction session specific for each storage provider. - /// - object Session { get; } - } -} \ No newline at end of file diff --git a/src/WorkflowCore/Services/WorkflowController.cs b/src/WorkflowCore/Services/WorkflowController.cs index 1fb97f821..6edb63aa7 100755 --- a/src/WorkflowCore/Services/WorkflowController.cs +++ b/src/WorkflowCore/Services/WorkflowController.cs @@ -53,7 +53,7 @@ public Task StartWorkflow(string workflowId, TData data = null, s return StartWorkflow(workflowId, null, data, reference); } - public async Task StartWorkflow(string workflowId, int? version, TData data = null, string reference=null, ITransaction transaction = null) + public async Task StartWorkflow(string workflowId, int? version, TData data = null, string reference=null) where TData : class, new() { @@ -91,7 +91,7 @@ public async Task StartWorkflow(string workflowId, int? version, await middlewareRunner.RunPreMiddleware(wf, def); } - string id = await _persistenceStore.CreateNewWorkflow(wf, transaction); + string id = await _persistenceStore.CreateNewWorkflow(wf); await _queueProvider.QueueWork(id, QueueType.Workflow); await _queueProvider.QueueWork(id, QueueType.Index); await _eventHub.PublishNotification(new WorkflowStarted diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index fe4f88cb5..79e9fe5b7 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -126,7 +126,6 @@ static void CreateIndexes(MongoPersistenceProvider instance) public async Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) { await WorkflowInstances.InsertOneAsync(workflow, cancellationToken: cancellationToken); - return workflow.Id; } From 66fc797496574c1ca0f4562951cc34dc859b9097 Mon Sep 17 00:00:00 2001 From: glucaci Date: Mon, 23 Aug 2021 15:08:52 +0200 Subject: [PATCH 167/342] Add transaction scope support --- .../Services/MongoPersistenceProvider.cs | 9 +++++---- .../WorkflowCore.Persistence.MongoDB.csproj | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index 79e9fe5b7..fd6d00a44 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -12,6 +12,7 @@ using WorkflowCore.Interface; using WorkflowCore.Models; using System.Threading; +using MongoDB.Extensions.Transactions; namespace WorkflowCore.Persistence.MongoDB.Services { @@ -115,13 +116,13 @@ static void CreateIndexes(MongoPersistenceProvider instance) } } - private IMongoCollection WorkflowInstances => _database.GetCollection(WorkflowCollectionName); + private IMongoCollection WorkflowInstances => _database.GetCollection(WorkflowCollectionName).AsTransactionCollection(); - private IMongoCollection EventSubscriptions => _database.GetCollection("wfc.subscriptions"); + private IMongoCollection EventSubscriptions => _database.GetCollection("wfc.subscriptions").AsTransactionCollection(); - private IMongoCollection Events => _database.GetCollection("wfc.events"); + private IMongoCollection Events => _database.GetCollection("wfc.events").AsTransactionCollection(); - private IMongoCollection ExecutionErrors => _database.GetCollection("wfc.execution_errors"); + private IMongoCollection ExecutionErrors => _database.GetCollection("wfc.execution_errors").AsTransactionCollection(); public async Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) { diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj index 13df8d4aa..20c32aaaf 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj +++ b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj @@ -22,7 +22,8 @@ - + + From 2020d305c03aa5775d4616012485f065f19f4347 Mon Sep 17 00:00:00 2001 From: john Date: Wed, 1 Sep 2021 09:09:23 +0300 Subject: [PATCH 168/342] Resolve #403, unnecessary log info --- src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs index 9d5edc575..bf3d97ba9 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs @@ -55,7 +55,7 @@ private async void PollRunnables(object target) { try { - _logger.LogInformation("Polling for runnable workflows"); + _logger.LogDebug("Polling for runnable workflows"); var runnables = await _persistenceStore.GetRunnableInstances(_dateTimeProvider.Now); foreach (var item in runnables) { @@ -86,7 +86,7 @@ private async void PollRunnables(object target) { try { - _logger.LogInformation("Polling for unprocessed events"); + _logger.LogDebug("Polling for unprocessed events"); var events = await _persistenceStore.GetRunnableEvents(_dateTimeProvider.Now); foreach (var item in events.ToList()) { From 7425294683eb64c2651836e7ea5fac3d83dd9401 Mon Sep 17 00:00:00 2001 From: John Demetriou Date: Thu, 2 Sep 2021 11:36:05 +0300 Subject: [PATCH 169/342] Delete ServiceCollectionExtensions.cs Empty class. Re-introduce if ever needed --- .../WorkflowCore.WebAPI/ServiceCollectionExtensions.cs | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 src/extensions/WorkflowCore.WebAPI/ServiceCollectionExtensions.cs diff --git a/src/extensions/WorkflowCore.WebAPI/ServiceCollectionExtensions.cs b/src/extensions/WorkflowCore.WebAPI/ServiceCollectionExtensions.cs deleted file mode 100644 index 3a2ead3db..000000000 --- a/src/extensions/WorkflowCore.WebAPI/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using System.Linq; - -namespace Microsoft.Extensions.DependencyInjection -{ - public static class ServiceCollectionExtensions - { - - } -} From b68bb062d7f20f78bd71a69048f045446c6fc466 Mon Sep 17 00:00:00 2001 From: glucaci Date: Fri, 3 Sep 2021 11:49:14 +0200 Subject: [PATCH 170/342] Revert and provide a new extension for creating db from outside --- .../ServiceCollectionExtensions.cs | 22 ++++++++++++++++++- .../Services/MongoPersistenceProvider.cs | 9 ++++---- .../WorkflowCore.Persistence.MongoDB.csproj | 3 +-- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Persistence.MongoDB/ServiceCollectionExtensions.cs index 87b0e689e..9534fe0b2 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/ServiceCollectionExtensions.cs @@ -1,6 +1,5 @@ using MongoDB.Driver; using System; -using System.Linq; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Persistence.MongoDB.Services; @@ -33,5 +32,26 @@ public static WorkflowOptions UseMongoDB( }); return options; } + + public static WorkflowOptions UseMongoDB( + this WorkflowOptions options, + Func createDatabase) + { + if (options == null) throw new ArgumentNullException(nameof(options)); + if (createDatabase == null) throw new ArgumentNullException(nameof(createDatabase)); + + options.UsePersistence(sp => + { + var db = createDatabase(sp); + return new MongoPersistenceProvider(db); + }); + options.Services.AddTransient(sp => + { + var db = createDatabase(sp); + return new WorkflowPurger(db); + }); + + return options; + } } } diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index fd6d00a44..79e9fe5b7 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -12,7 +12,6 @@ using WorkflowCore.Interface; using WorkflowCore.Models; using System.Threading; -using MongoDB.Extensions.Transactions; namespace WorkflowCore.Persistence.MongoDB.Services { @@ -116,13 +115,13 @@ static void CreateIndexes(MongoPersistenceProvider instance) } } - private IMongoCollection WorkflowInstances => _database.GetCollection(WorkflowCollectionName).AsTransactionCollection(); + private IMongoCollection WorkflowInstances => _database.GetCollection(WorkflowCollectionName); - private IMongoCollection EventSubscriptions => _database.GetCollection("wfc.subscriptions").AsTransactionCollection(); + private IMongoCollection EventSubscriptions => _database.GetCollection("wfc.subscriptions"); - private IMongoCollection Events => _database.GetCollection("wfc.events").AsTransactionCollection(); + private IMongoCollection Events => _database.GetCollection("wfc.events"); - private IMongoCollection ExecutionErrors => _database.GetCollection("wfc.execution_errors").AsTransactionCollection(); + private IMongoCollection ExecutionErrors => _database.GetCollection("wfc.execution_errors"); public async Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) { diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj index 20c32aaaf..13df8d4aa 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj +++ b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj @@ -22,8 +22,7 @@ - - + From d6ab06e56b6d4b62e6a26deb85232974dc0de8f5 Mon Sep 17 00:00:00 2001 From: Mohamed Rslan Date: Sat, 4 Sep 2021 19:08:45 +0300 Subject: [PATCH 171/342] Upgrade NEST version to support elastic 7 fix startup exception "ArgumentException: Requested value 'data_cold' was not found" which the NEST V7.5.1 library doesn't have all new elastic roles enum mappings --- .../WorkflowCore.Providers.Elasticsearch.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj b/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj index db78bebb7..7bf5600b8 100644 --- a/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj +++ b/src/providers/WorkflowCore.Providers.Elasticsearch/WorkflowCore.Providers.Elasticsearch.csproj @@ -13,7 +13,7 @@ - + From ea6f184c47b5ddc3e9914b0d829590d195ceac83 Mon Sep 17 00:00:00 2001 From: Mohamed Rslan Date: Sat, 4 Sep 2021 19:24:16 +0300 Subject: [PATCH 172/342] Upgrade NEST Test version to support elastic 7 --- .../WorkflowCore.Tests.Elasticsearch.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj index 0ed01e311..60e631bd7 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj +++ b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj @@ -8,7 +8,7 @@ - + From 1c199e4a7a4fa89182843abfc8176fb0d6762114 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 11 Sep 2021 19:53:07 -0700 Subject: [PATCH 173/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 13d001297..cca812e1d 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.5.3 - 3.5.4.0 - 3.5.4.0 + 3.5.5 + 3.5.5.0 + 3.5.5.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.5.4 + 3.5.5 From 2216ad4f10ac3155e1a4912c0fa6294b22831381 Mon Sep 17 00:00:00 2001 From: Sergii Kram Date: Tue, 14 Sep 2021 11:32:30 +0300 Subject: [PATCH 174/342] Fix SQL Server tests The repository 'microsoft/mssql-server-linux' is no longer maintained and container image cannot be pulled. 'mcr.microsoft.com/mssql/server' should be used instead. See https://cloudblogs.microsoft.com/sqlserver/2021/05/20/microsoft-sql-server-linux-based-container-images-to-be-available-only-from-the-microsoft-container-registry/ for details. --- test/WorkflowCore.Tests.SqlServer/DockerSetup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs b/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs index 74aff9487..b9d15ddff 100644 --- a/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs +++ b/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs @@ -11,7 +11,7 @@ public class SqlDockerSetup : DockerSetup public static string ConnectionString { get; set; } public static string ScenarioConnectionString { get; set; } - public override string ImageName => "microsoft/mssql-server-linux"; + public override string ImageName => "mcr.microsoft.com/mssql/server"; public override int InternalPort => 1433; public override TimeSpan TimeOut => TimeSpan.FromSeconds(120); From 2f9908b78977cb6ce0fec20934c638a875b5d19e Mon Sep 17 00:00:00 2001 From: Sergii Kram Date: Tue, 14 Sep 2021 12:25:55 +0300 Subject: [PATCH 175/342] Fix DynamoDB tests The latest 'amazon/dynamodb-local' image introduces breaking change and requires dummy credentials, see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.DownloadingAndRunning.html. Without the fix tests fail with the timeout error in DockerSetup.StartContainer method but the real error is "Unable to get IAM security credentials from EC2 Instance Metadata Service." in the DynamoDbDockerSetup.TestReady method. --- test/WorkflowCore.Tests.DynamoDB/DynamoDbDockerSetup.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/WorkflowCore.Tests.DynamoDB/DynamoDbDockerSetup.cs b/test/WorkflowCore.Tests.DynamoDB/DynamoDbDockerSetup.cs index b9458fd1e..83501a6d5 100644 --- a/test/WorkflowCore.Tests.DynamoDB/DynamoDbDockerSetup.cs +++ b/test/WorkflowCore.Tests.DynamoDB/DynamoDbDockerSetup.cs @@ -11,7 +11,7 @@ public class DynamoDbDockerSetup : DockerSetup { public static string ConnectionString { get; set; } - public static AWSCredentials Credentials => new EnvironmentVariablesAWSCredentials(); + public static AWSCredentials Credentials => new BasicAWSCredentials("DUMMYIDEXAMPLE", "DUMMYEXAMPLEKEY"); public override string ImageName => @"amazon/dynamodb-local"; public override int InternalPort => 8000; @@ -30,7 +30,7 @@ public override bool TestReady() { ServiceURL = $"http://localhost:{ExternalPort}" }; - AmazonDynamoDBClient client = new AmazonDynamoDBClient(clientConfig); + AmazonDynamoDBClient client = new AmazonDynamoDBClient(Credentials, clientConfig); var resp = client.ListTablesAsync().Result; return resp.HttpStatusCode == HttpStatusCode.OK; From f2ac1255e318b1b6c1cea216655de258ed05c7a7 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sun, 19 Sep 2021 09:15:13 -0700 Subject: [PATCH 176/342] Update Directory.Build.props --- src/Directory.Build.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index cca812e1d..26c64f3ff 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -5,9 +5,9 @@ git https://github.com/danielgerlag/workflow-core.git 3.5.5 - 3.5.5.0 - 3.5.5.0 + 3.5.6.0 + 3.5.6.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.5.5 + 3.5.6 From beadef890d747be190d1adc27ce0773109be324f Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 8 Oct 2021 00:48:53 +0300 Subject: [PATCH 177/342] Fix issue #926 --- src/WorkflowCore/Services/SyncWorkflowRunner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WorkflowCore/Services/SyncWorkflowRunner.cs b/src/WorkflowCore/Services/SyncWorkflowRunner.cs index d0e0dcd89..5317a8966 100644 --- a/src/WorkflowCore/Services/SyncWorkflowRunner.cs +++ b/src/WorkflowCore/Services/SyncWorkflowRunner.cs @@ -87,7 +87,7 @@ public async Task RunWorkflowSync(string workflowId, in { while ((wf.Status == WorkflowStatus.Runnable) && !token.IsCancellationRequested) { - await _executor.Execute(wf); + await _executor.Execute(wf, token); if (persistSate) await _persistenceStore.PersistWorkflow(wf, token); } From 2452d73a54e0a8f0fb3bad30e0de822eda5dfe44 Mon Sep 17 00:00:00 2001 From: MitchellVermaning Date: Wed, 13 Oct 2021 10:48:37 +0200 Subject: [PATCH 178/342] Update of "System.Linq.Dynamic.Core" package **Describe the bug** Hello! Thank you for sharing this powerful library. Last week I have reported a bug in the Linq.Dynamic.Core package (https://github.com/zzzprojects/System.Linq.Dynamic.Core/issues/545). The `DynamicExpressionParser.ParseLambda()` function was unable to escape backslashes correctly. Can you please update this package to the newest version v1.2.13. Thank you! --- src/WorkflowCore.DSL/WorkflowCore.DSL.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj b/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj index 230286071..1a0130fc9 100644 --- a/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj +++ b/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj @@ -11,7 +11,7 @@ - + From 5fbaa59f9ed71461b7800d760178ec658b1b7f53 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Thu, 14 Oct 2021 09:51:59 -0700 Subject: [PATCH 179/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 26c64f3ff..e276b701b 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.5.5 - 3.5.6.0 - 3.5.6.0 + 3.5.7 + 3.5.7.0 + 3.5.7.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.5.6 + 3.5.7 From 583a2503cf5de5c88e12f2938f5d017e6f04bcd3 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 15 Oct 2021 12:28:10 -0700 Subject: [PATCH 180/342] scheduled commands --- .../Persistence/IPersistenceProvider.cs | 2 +- .../IScheduledCommandRepository.cs | 18 +++++ src/WorkflowCore/Models/ScheduledCommand.cs | 16 +++++ .../BackgroundTasks/RunnablePoller.cs | 69 ++++++++++++++++++- .../BackgroundTasks/WorkflowConsumer.cs | 22 ++++-- .../MemoryPersistenceProvider.cs | 12 ++++ .../TransientMemoryPersistenceProvider.cs | 12 ++++ src/WorkflowCore/WorkflowCore.csproj | 1 + .../EntityFrameworkPersistenceProvider.cs | 12 ++++ .../Services/MongoPersistenceProvider.cs | 51 ++++++++++++++ .../Services/RavendbPersistenceProvider.cs | 15 +++- .../Services/DynamoPersistenceProvider.cs | 12 ++++ .../Services/CosmosDbPersistenceProvider.cs | 12 ++++ .../Services/RedisPersistenceProvider.cs | 12 ++++ .../Scenarios/DelayScenario.cs | 57 +++++++++++++++ test/WorkflowCore.Testing/WorkflowTest.cs | 2 +- .../Scenarios/MongoDelayScenario.cs | 26 +++++++ .../Scenarios/PostgresDelayScenario.cs | 20 ++++++ .../Scenarios/SqlServerDelayScenario.cs | 20 ++++++ 19 files changed, 381 insertions(+), 10 deletions(-) create mode 100644 src/WorkflowCore/Interface/Persistence/IScheduledCommandRepository.cs create mode 100644 src/WorkflowCore/Models/ScheduledCommand.cs create mode 100644 test/WorkflowCore.IntegrationTests/Scenarios/DelayScenario.cs create mode 100644 test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDelayScenario.cs create mode 100644 test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresDelayScenario.cs create mode 100644 test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerDelayScenario.cs diff --git a/src/WorkflowCore/Interface/Persistence/IPersistenceProvider.cs b/src/WorkflowCore/Interface/Persistence/IPersistenceProvider.cs index 7bff56345..4b83f5920 100644 --- a/src/WorkflowCore/Interface/Persistence/IPersistenceProvider.cs +++ b/src/WorkflowCore/Interface/Persistence/IPersistenceProvider.cs @@ -6,7 +6,7 @@ namespace WorkflowCore.Interface { - public interface IPersistenceProvider : IWorkflowRepository, ISubscriptionRepository, IEventRepository + public interface IPersistenceProvider : IWorkflowRepository, ISubscriptionRepository, IEventRepository, IScheduledCommandRepository { Task PersistErrors(IEnumerable errors, CancellationToken cancellationToken = default); diff --git a/src/WorkflowCore/Interface/Persistence/IScheduledCommandRepository.cs b/src/WorkflowCore/Interface/Persistence/IScheduledCommandRepository.cs new file mode 100644 index 000000000..a86bccc42 --- /dev/null +++ b/src/WorkflowCore/Interface/Persistence/IScheduledCommandRepository.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using WorkflowCore.Models; + +namespace WorkflowCore.Interface +{ + public interface IScheduledCommandRepository + { + bool SupportsScheduledCommands { get; } + + Task ScheduleCommand(ScheduledCommand command); + + Task ProcessCommands(DateTimeOffset asOf, Func action, CancellationToken cancellationToken = default); + } +} diff --git a/src/WorkflowCore/Models/ScheduledCommand.cs b/src/WorkflowCore/Models/ScheduledCommand.cs new file mode 100644 index 000000000..de3dcc5dd --- /dev/null +++ b/src/WorkflowCore/Models/ScheduledCommand.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace WorkflowCore.Models +{ + public class ScheduledCommand + { + public const string ProcessWorkflow = "ProcessWorkflow"; + public const string ProcessEvent = "ProcessEvent"; + + public string CommandName { get; set; } + public string Data { get; set; } + public long ExecuteTime { get; set; } + } +} diff --git a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs index 9d5edc575..4e7101d57 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Logging; using WorkflowCore.Interface; using WorkflowCore.Models; @@ -48,6 +49,13 @@ public void Stop() /// Poll the persistence store for stashed unpublished events /// private async void PollRunnables(object target) + { + await PollWorkflows(); + await PollEvents(); + await PollCommands(); + } + + private async Task PollWorkflows() { try { @@ -55,10 +63,20 @@ private async void PollRunnables(object target) { try { - _logger.LogInformation("Polling for runnable workflows"); + _logger.LogInformation("Polling for runnable workflows"); var runnables = await _persistenceStore.GetRunnableInstances(_dateTimeProvider.Now); foreach (var item in runnables) { + if (_persistenceStore.SupportsScheduledCommands) + { + await _persistenceStore.ScheduleCommand(new ScheduledCommand() + { + CommandName = ScheduledCommand.ProcessWorkflow, + Data = item, + ExecuteTime = _dateTimeProvider.UtcNow.Ticks + }); + continue; + } if (_greylist.Contains($"wf:{item}")) { _logger.LogDebug($"Got greylisted workflow {item}"); @@ -79,17 +97,30 @@ private async void PollRunnables(object target) { _logger.LogError(ex, ex.Message); } + } + private async Task PollEvents() + { try { if (await _lockProvider.AcquireLock("unprocessed events", new CancellationToken())) { try { - _logger.LogInformation("Polling for unprocessed events"); + _logger.LogInformation("Polling for unprocessed events"); var events = await _persistenceStore.GetRunnableEvents(_dateTimeProvider.Now); foreach (var item in events.ToList()) { + if (_persistenceStore.SupportsScheduledCommands) + { + await _persistenceStore.ScheduleCommand(new ScheduledCommand() + { + CommandName = ScheduledCommand.ProcessEvent, + Data = item, + ExecuteTime = _dateTimeProvider.UtcNow.Ticks + }); + continue; + } if (_greylist.Contains($"evt:{item}")) { _logger.LogDebug($"Got greylisted event {item}"); @@ -111,5 +142,39 @@ private async void PollRunnables(object target) _logger.LogError(ex, ex.Message); } } + + private async Task PollCommands() + { + try + { + if (await _lockProvider.AcquireLock("poll-commands", new CancellationToken())) + { + try + { + _logger.LogInformation("Polling for scheduled commands"); + await _persistenceStore.ProcessCommands(new DateTimeOffset(_dateTimeProvider.UtcNow), async (command) => + { + switch (command.CommandName) + { + case ScheduledCommand.ProcessWorkflow: + await _queueProvider.QueueWork(command.Data, QueueType.Workflow); + break; + case ScheduledCommand.ProcessEvent: + await _queueProvider.QueueWork(command.Data, QueueType.Event); + break; + } + }); + } + finally + { + await _lockProvider.ReleaseLock("poll-commands"); + } + } + } + catch (Exception ex) + { + _logger.LogError(ex, ex.Message); + } + } } } diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index 6e5c1d3c1..a387848b6 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -69,11 +69,25 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance await _persistenceStore.PersistErrors(result.Errors, cancellationToken); - var readAheadTicks = _datetimeProvider.UtcNow.Add(Options.PollInterval).Ticks; - - if ((workflow.Status == WorkflowStatus.Runnable) && workflow.NextExecution.HasValue && workflow.NextExecution.Value < readAheadTicks) + if ((workflow.Status == WorkflowStatus.Runnable) && workflow.NextExecution.HasValue) { - new Task(() => FutureQueue(workflow, cancellationToken)).Start(); + var readAheadTicks = _datetimeProvider.UtcNow.Add(Options.PollInterval).Ticks; + if (workflow.NextExecution.Value < readAheadTicks) + { + new Task(() => FutureQueue(workflow, cancellationToken)).Start(); + } + else + { + if (_persistenceStore.SupportsScheduledCommands) + { + await _persistenceStore.ScheduleCommand(new ScheduledCommand() + { + CommandName = ScheduledCommand.ProcessWorkflow, + Data = workflow.Id, + ExecuteTime = workflow.NextExecution.Value + }); + } + } } } } diff --git a/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs b/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs index 96ea772af..e983f8fd5 100644 --- a/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs +++ b/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs @@ -24,6 +24,8 @@ public class MemoryPersistenceProvider : ISingletonMemoryProvider private readonly List _events = new List(); private readonly List _errors = new List(); + public bool SupportsScheduledCommands => false; + public async Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken _ = default) { lock (_instances) @@ -255,6 +257,16 @@ public async Task PersistErrors(IEnumerable errors, Cancellation _errors.AddRange(errors); } } + + public Task ScheduleCommand(ScheduledCommand command) + { + throw new NotImplementedException(); + } + + public Task ProcessCommands(DateTimeOffset asOf, Func action, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } } #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously diff --git a/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs b/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs index c2fab66e1..0a94c6f8e 100644 --- a/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs +++ b/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs @@ -11,6 +11,8 @@ public class TransientMemoryPersistenceProvider : IPersistenceProvider { private readonly ISingletonMemoryProvider _innerService; + public bool SupportsScheduledCommands => false; + public TransientMemoryPersistenceProvider(ISingletonMemoryProvider innerService) { _innerService = innerService; @@ -56,5 +58,15 @@ public TransientMemoryPersistenceProvider(ISingletonMemoryProvider innerService) public Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry, CancellationToken _ = default) => _innerService.SetSubscriptionToken(eventSubscriptionId, token, workerId, expiry); public Task ClearSubscriptionToken(string eventSubscriptionId, string token, CancellationToken _ = default) => _innerService.ClearSubscriptionToken(eventSubscriptionId, token); + + public Task ScheduleCommand(ScheduledCommand command) + { + throw new NotImplementedException(); + } + + public Task ProcessCommands(DateTimeOffset asOf, Func action, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } } } diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 1457092bd..800ef9c08 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -26,6 +26,7 @@ + diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs index e0c7082fd..40bd892e8 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs @@ -17,6 +17,8 @@ public class EntityFrameworkPersistenceProvider : IPersistenceProvider private readonly bool _canMigrateDB; private readonly IWorkflowDbContextFactory _contextFactory; + public bool SupportsScheduledCommands => false; + public EntityFrameworkPersistenceProvider(IWorkflowDbContextFactory contextFactory, bool canCreateDB, bool canMigrateDB) { _contextFactory = contextFactory; @@ -365,5 +367,15 @@ public async Task ClearSubscriptionToken(string eventSubscriptionId, string toke await db.SaveChangesAsync(cancellationToken); } } + + public Task ScheduleCommand(ScheduledCommand command) + { + throw new NotImplementedException(); + } + + public Task ProcessCommands(DateTimeOffset asOf, Func action, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } } } diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index 79e9fe5b7..ac65eb39b 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -83,6 +83,8 @@ static MongoPersistenceProvider() BsonClassMap.RegisterClassMap(x => x.AutoMap()); BsonClassMap.RegisterClassMap(x => x.AutoMap()); BsonClassMap.RegisterClassMap(x => x.AutoMap()); + BsonClassMap.RegisterClassMap(x => x.AutoMap()) + .SetIgnoreExtraElements(true); } static bool indexesCreated = false; @@ -111,6 +113,17 @@ static void CreateIndexes(MongoPersistenceProvider instance) .Ascending(x => x.EventKey), new CreateIndexOptions { Background = true, Name = "idx_namekey" })); + instance.ScheduledCommands.Indexes.CreateOne(new CreateIndexModel( + Builders.IndexKeys + .Descending(x => x.ExecuteTime), + new CreateIndexOptions { Background = true, Name = "idx_exectime" })); + + instance.ScheduledCommands.Indexes.CreateOne(new CreateIndexModel( + Builders.IndexKeys + .Ascending(x => x.CommandName) + .Ascending(x => x.Data), + new CreateIndexOptions { Background = true, Unique = true, Name = "idx_key" })); + indexesCreated = true; } } @@ -123,6 +136,8 @@ static void CreateIndexes(MongoPersistenceProvider instance) private IMongoCollection ExecutionErrors => _database.GetCollection("wfc.execution_errors"); + private IMongoCollection ScheduledCommands => _database.GetCollection("wfc.scheduled_commands"); + public async Task CreateNewWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) { await WorkflowInstances.InsertOneAsync(workflow, cancellationToken: cancellationToken); @@ -291,5 +306,41 @@ public async Task PersistErrors(IEnumerable errors, Cancellation if (errors.Any()) await ExecutionErrors.InsertManyAsync(errors, cancellationToken: cancellationToken); } + + public bool SupportsScheduledCommands => true; + + public async Task ScheduleCommand(ScheduledCommand command) + { + try + { + await ScheduledCommands.InsertOneAsync(command); + } + catch (MongoBulkWriteException ex) + { + if (ex.WriteErrors.All(x => x.Category == ServerErrorCategory.DuplicateKey)) + return; + throw; + } + } + + public async Task ProcessCommands(DateTimeOffset asOf, Func action, CancellationToken cancellationToken = default) + { + var cursor = await ScheduledCommands.FindAsync(x => x.ExecuteTime < asOf.UtcDateTime.Ticks); + while (await cursor.MoveNextAsync(cancellationToken)) + { + foreach (var command in cursor.Current) + { + try + { + await action(command); + await ScheduledCommands.DeleteOneAsync(x => x.CommandName == command.CommandName && x.Data == command.Data); + } + catch (Exception) + { + //TODO: add logger + } + } + } + } } } diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs index d115f1eb2..695b8e31f 100644 --- a/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs @@ -18,7 +18,9 @@ public class RavendbPersistenceProvider : IPersistenceProvider private readonly IDocumentStore _database; static bool indexesCreated = false; - public RavendbPersistenceProvider(IDocumentStore database) + public bool SupportsScheduledCommands => false; + + public RavendbPersistenceProvider(IDocumentStore database) { _database = database; CreateIndexes(this); @@ -316,5 +318,14 @@ public async Task PersistErrors(IEnumerable errors, Cancellation } } - } + public Task ScheduleCommand(ScheduledCommand command) + { + throw new NotImplementedException(); + } + + public Task ProcessCommands(DateTimeOffset asOf, Func action, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + } } diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs index d3828389a..1126b6c20 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs @@ -24,6 +24,8 @@ public class DynamoPersistenceProvider : IPersistenceProvider public const string SUBCRIPTION_TABLE = "subscriptions"; public const string EVENT_TABLE = "events"; + public bool SupportsScheduledCommands => false; + public DynamoPersistenceProvider(AWSCredentials credentials, AmazonDynamoDBConfig config, IDynamoDbProvisioner provisioner, string tablePrefix, ILoggerFactory logFactory) { _logger = logFactory.CreateLogger(); @@ -469,5 +471,15 @@ public async Task ClearSubscriptionToken(string eventSubscriptionId, string toke await _client.UpdateItemAsync(request, cancellationToken); } + + public Task ScheduleCommand(ScheduledCommand command) + { + throw new NotImplementedException(); + } + + public Task ProcessCommands(DateTimeOffset asOf, Func action, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs index 36e51b86c..644009df2 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs @@ -35,6 +35,8 @@ public CosmosDbPersistenceProvider( _subscriptionContainer = new Lazy(() => _clientFactory.GetCosmosClient().GetDatabase(_dbId).GetContainer(cosmosDbStorageOptions.SubscriptionContainerName)); } + public bool SupportsScheduledCommands => false; + public async Task ClearSubscriptionToken(string eventSubscriptionId, string token, CancellationToken cancellationToken = default) { var existing = await _subscriptionContainer.Value.ReadItemAsync(eventSubscriptionId, new PartitionKey(eventSubscriptionId)); @@ -225,6 +227,16 @@ public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken c await _workflowContainer.Value.UpsertItemAsync(PersistedWorkflow.FromInstance(workflow), cancellationToken: cancellationToken); } + public Task ProcessCommands(DateTimeOffset asOf, Func action, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public Task ScheduleCommand(ScheduledCommand command) + { + throw new NotImplementedException(); + } + public async Task SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry, CancellationToken cancellationToken) { var sub = await _subscriptionContainer.Value.ReadItemAsync(eventSubscriptionId, new PartitionKey(eventSubscriptionId), cancellationToken: cancellationToken); diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs index dcd932af0..cde65e2e5 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs @@ -28,6 +28,8 @@ public class RedisPersistenceProvider : IPersistenceProvider private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; private readonly bool _removeComplete; + public bool SupportsScheduledCommands => false; + public RedisPersistenceProvider(string connectionString, string prefix, bool removeComplete, ILoggerFactory logFactory) { _connectionString = connectionString; @@ -232,5 +234,15 @@ public Task PersistErrors(IEnumerable errors, CancellationToken public void EnsureStoreExists() { } + + public Task ScheduleCommand(ScheduledCommand command) + { + throw new NotImplementedException(); + } + + public Task ProcessCommands(DateTimeOffset asOf, Func action, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } } } diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/DelayScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/DelayScenario.cs new file mode 100644 index 000000000..704b27d79 --- /dev/null +++ b/test/WorkflowCore.IntegrationTests/Scenarios/DelayScenario.cs @@ -0,0 +1,57 @@ +using System; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using Xunit; +using FluentAssertions; +using WorkflowCore.Testing; + +namespace WorkflowCore.IntegrationTests.Scenarios +{ + public class DelayWorkflow : IWorkflow + { + internal static int Step1Ticker = 0; + internal static int Step2Ticker = 0; + + public string Id => "DelayWorkflow"; + public int Version => 1; + public void Build(IWorkflowBuilder builder) + { + builder + .StartWith(context => Step1Ticker++) + .Delay(data => data.WaitTime) + .Then(context => Step2Ticker++); + + } + + public class MyDataClass + { + public TimeSpan WaitTime { get; set; } + } + } + + public class DelayScenario : WorkflowTest + { + public DelayScenario() + { + Setup(); + } + + [Fact] + public void Scenario() + { + DelayWorkflow.Step1Ticker = 0; + DelayWorkflow.Step2Ticker = 0; + + var workflowId = StartWorkflow(new DelayWorkflow.MyDataClass() + { + WaitTime = Host.Options.PollInterval.Add(TimeSpan.FromSeconds(1)) + }); + WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); + + GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); + UnhandledStepErrors.Count.Should().Be(0); + DelayWorkflow.Step1Ticker.Should().Be(1); + DelayWorkflow.Step2Ticker.Should().Be(1); + } + } +} diff --git a/test/WorkflowCore.Testing/WorkflowTest.cs b/test/WorkflowCore.Testing/WorkflowTest.cs index 46a6d0ce8..bf0eb97ab 100644 --- a/test/WorkflowCore.Testing/WorkflowTest.cs +++ b/test/WorkflowCore.Testing/WorkflowTest.cs @@ -46,7 +46,7 @@ protected void Host_OnStepError(WorkflowInstance workflow, WorkflowStep step, Ex protected virtual void ConfigureServices(IServiceCollection services) { - services.AddWorkflow(); + services.AddWorkflow(options => options.UsePollInterval(TimeSpan.FromSeconds(3))); } public string StartWorkflow(TData data) diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDelayScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDelayScenario.cs new file mode 100644 index 000000000..511aa79fb --- /dev/null +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDelayScenario.cs @@ -0,0 +1,26 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using MongoDB.Bson.Serialization; +using WorkflowCore.IntegrationTests.Scenarios; +using Xunit; + +namespace WorkflowCore.Tests.MongoDB.Scenarios +{ + [Collection("Mongo collection")] + public class MongoDelayScenario : DelayScenario + { + public MongoDelayScenario() : base() + { + BsonClassMap.RegisterClassMap(map => map.AutoMap()); + } + + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(cfg => + { + cfg.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests"); + cfg.UsePollInterval(TimeSpan.FromSeconds(2)); + }); + } + } +} diff --git a/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresDelayScenario.cs b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresDelayScenario.cs new file mode 100644 index 000000000..649632ac5 --- /dev/null +++ b/test/WorkflowCore.Tests.PostgreSQL/Scenarios/PostgresDelayScenario.cs @@ -0,0 +1,20 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using Xunit; + +namespace WorkflowCore.Tests.PostgreSQL.Scenarios +{ + [Collection("Postgres collection")] + public class PostgresDelayScenario : DelayScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(cfg => + { + cfg.UsePostgreSQL(PostgresDockerSetup.ScenarioConnectionString, true, true); + cfg.UsePollInterval(TimeSpan.FromSeconds(2)); + }); + } + } +} diff --git a/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerDelayScenario.cs b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerDelayScenario.cs new file mode 100644 index 000000000..5e623c1db --- /dev/null +++ b/test/WorkflowCore.Tests.SqlServer/Scenarios/SqlServerDelayScenario.cs @@ -0,0 +1,20 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using Xunit; + +namespace WorkflowCore.Tests.SqlServer.Scenarios +{ + [Collection("SqlServer collection")] + public class SqlServerDelayScenario : DelayScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(cfg => + { + cfg.UseSqlServer(SqlDockerSetup.ScenarioConnectionString, true, true); + cfg.UsePollInterval(TimeSpan.FromSeconds(2)); + }); + } + } +} From b08f2c069dce0a22b7b08cad15569a05a571f4fc Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 15 Oct 2021 15:11:33 -0700 Subject: [PATCH 181/342] ef migrations --- src/Directory.Build.props | 8 +- .../BackgroundTasks/RunnablePoller.cs | 38 +- .../ExtensionMethods.cs | 20 + .../Models/PersistedScheduledCommand.cs | 20 + .../EntityFrameworkPersistenceProvider.cs | 41 +- .../Services/WorkflowDbContext.cs | 4 + ...lowCore.Persistence.EntityFramework.csproj | 2 +- ...11015215708_scheduled-commands.Designer.cs | 357 +++++++++++++++++ .../20211015215708_scheduled-commands.cs | 337 ++++++++++++++++ .../MysqlPersistenceProviderModelSnapshot.cs | 153 ++++--- .../WorkflowCore.Persistence.MySQL.csproj | 2 +- ...11015204734_scheduled-commands.Designer.cs | 366 +++++++++++++++++ .../20211015204734_scheduled-commands.cs | 43 ++ ...ostgresPersistenceProviderModelSnapshot.cs | 146 ++++--- ...11015215114_scheduled-commands.Designer.cs | 379 ++++++++++++++++++ .../20211015215114_scheduled-commands.cs | 43 ++ ...lServerPersistenceProviderModelSnapshot.cs | 60 ++- .../Scenarios/MysqlDelayScenario.cs | 20 + 18 files changed, 1902 insertions(+), 137 deletions(-) create mode 100644 src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedScheduledCommand.cs create mode 100644 src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211015215708_scheduled-commands.Designer.cs create mode 100644 src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211015215708_scheduled-commands.cs create mode 100644 src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211015204734_scheduled-commands.Designer.cs create mode 100644 src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211015204734_scheduled-commands.cs create mode 100644 src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211015215114_scheduled-commands.Designer.cs create mode 100644 src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211015215114_scheduled-commands.cs create mode 100644 test/WorkflowCore.Tests.MySQL/Scenarios/MysqlDelayScenario.cs diff --git a/src/Directory.Build.props b/src/Directory.Build.props index e276b701b..7c162693d 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.5.7 - 3.5.7.0 - 3.5.7.0 + 3.6.0 + 3.6.0.0 + 3.6.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.5.7 + 3.6.0 diff --git a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs index 4e7101d57..b40a7a208 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs @@ -69,13 +69,20 @@ private async Task PollWorkflows() { if (_persistenceStore.SupportsScheduledCommands) { - await _persistenceStore.ScheduleCommand(new ScheduledCommand() + try { - CommandName = ScheduledCommand.ProcessWorkflow, - Data = item, - ExecuteTime = _dateTimeProvider.UtcNow.Ticks - }); - continue; + await _persistenceStore.ScheduleCommand(new ScheduledCommand() + { + CommandName = ScheduledCommand.ProcessWorkflow, + Data = item, + ExecuteTime = _dateTimeProvider.UtcNow.Ticks + }); + continue; + } + catch (Exception ex) + { + _logger.LogError(ex, ex.Message); + } } if (_greylist.Contains($"wf:{item}")) { @@ -113,13 +120,20 @@ private async Task PollEvents() { if (_persistenceStore.SupportsScheduledCommands) { - await _persistenceStore.ScheduleCommand(new ScheduledCommand() + try { - CommandName = ScheduledCommand.ProcessEvent, - Data = item, - ExecuteTime = _dateTimeProvider.UtcNow.Ticks - }); - continue; + await _persistenceStore.ScheduleCommand(new ScheduledCommand() + { + CommandName = ScheduledCommand.ProcessEvent, + Data = item, + ExecuteTime = _dateTimeProvider.UtcNow.Ticks + }); + continue; + } + catch (Exception ex) + { + _logger.LogError(ex, ex.Message); + } } if (_greylist.Contains($"evt:{item}")) { diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs index c978131d1..b0b2b1d99 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs @@ -123,6 +123,16 @@ internal static PersistedEvent ToPersistable(this Event instance) return result; } + internal static PersistedScheduledCommand ToPersistable(this ScheduledCommand instance) + { + var result = new PersistedScheduledCommand(); + result.CommandName = instance.CommandName; + result.Data = instance.Data; + result.ExecuteTime = instance.ExecuteTime; + + return result; + } + internal static WorkflowInstance ToWorkflowInstance(this PersistedWorkflow instance) { WorkflowInstance result = new WorkflowInstance(); @@ -219,5 +229,15 @@ internal static Event ToEvent(this PersistedEvent instance) return result; } + + internal static ScheduledCommand ToScheduledCommand(this PersistedScheduledCommand instance) + { + var result = new ScheduledCommand(); + result.CommandName = instance.CommandName; + result.Data = instance.Data; + result.ExecuteTime = instance.ExecuteTime; + + return result; + } } } diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedScheduledCommand.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedScheduledCommand.cs new file mode 100644 index 000000000..7dad156a3 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Models/PersistedScheduledCommand.cs @@ -0,0 +1,20 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.Linq; + +namespace WorkflowCore.Persistence.EntityFramework.Models +{ + public class PersistedScheduledCommand + { + [Key] + public long PersistenceId { get; set; } + + [MaxLength(200)] + public string CommandName { get; set; } + + [MaxLength(500)] + public string Data { get; set; } + + public long ExecuteTime { get; set; } + } +} diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs index 40bd892e8..56dd7f90c 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs @@ -17,7 +17,7 @@ public class EntityFrameworkPersistenceProvider : IPersistenceProvider private readonly bool _canMigrateDB; private readonly IWorkflowDbContextFactory _contextFactory; - public bool SupportsScheduledCommands => false; + public bool SupportsScheduledCommands => true; public EntityFrameworkPersistenceProvider(IWorkflowDbContextFactory contextFactory, bool canCreateDB, bool canMigrateDB) { @@ -368,14 +368,45 @@ public async Task ClearSubscriptionToken(string eventSubscriptionId, string toke } } - public Task ScheduleCommand(ScheduledCommand command) + public async Task ScheduleCommand(ScheduledCommand command) { - throw new NotImplementedException(); + try + { + using (var db = ConstructDbContext()) + { + var persistable = command.ToPersistable(); + var result = db.Set().Add(persistable); + await db.SaveChangesAsync(); + } + } + catch (DbUpdateException) + { + //log + } } - public Task ProcessCommands(DateTimeOffset asOf, Func action, CancellationToken cancellationToken = default) + public async Task ProcessCommands(DateTimeOffset asOf, Func action, CancellationToken cancellationToken = default) { - throw new NotImplementedException(); + using (var db = ConstructDbContext()) + { + var cursor = db.Set() + .Where(x => x.ExecuteTime < asOf.UtcDateTime.Ticks) + .AsAsyncEnumerable(); + + await foreach (var command in cursor) + { + try + { + await action(command.ToScheduledCommand()); + db.Set().Remove(command); + await db.SaveChangesAsync(); + } + catch (Exception) + { + //TODO: add logger + } + } + } } } } diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs index 7b80db3da..645a26c3d 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs @@ -38,6 +38,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) events.HasIndex(x => x.EventTime); events.HasIndex(x => x.IsProcessed); + var commands = modelBuilder.Entity(); + commands.HasIndex(x => x.ExecuteTime); + commands.HasIndex(x => new { x.CommandName, x.Data}).IsUnique(); + ConfigureWorkflowStorage(workflows); ConfigureExecutionPointerStorage(executionPointers); ConfigureExecutionErrorStorage(executionErrors); diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index 39627c7c9..6e1206632 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -3,7 +3,7 @@ Workflow Core EntityFramework Core Persistence Provider Daniel Gerlag - netstandard2.0 + netstandard2.1 WorkflowCore.Persistence.EntityFramework WorkflowCore.Persistence.EntityFramework workflow;.NET;Core;state machine;WorkflowCore;EntityFramework;EntityFrameworkCore diff --git a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211015215708_scheduled-commands.Designer.cs b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211015215708_scheduled-commands.Designer.cs new file mode 100644 index 000000000..9573baf3e --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211015215708_scheduled-commands.Designer.cs @@ -0,0 +1,357 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using WorkflowCore.Persistence.MySQL; + +namespace WorkflowCore.Persistence.MySQL.Migrations +{ + [DbContext(typeof(MysqlContext))] + [Migration("20211015215708_scheduled-commands")] + partial class scheduledcommands + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 64) + .HasAnnotation("ProductVersion", "5.0.8"); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("EventData") + .HasColumnType("longtext"); + + b.Property("EventId") + .HasColumnType("char(36)"); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("EventTime") + .HasColumnType("datetime(6)"); + + b.Property("IsProcessed") + .HasColumnType("tinyint(1)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventId") + .IsUnique(); + + b.HasIndex("EventTime"); + + b.HasIndex("IsProcessed"); + + b.HasIndex("EventName", "EventKey"); + + b.ToTable("Event"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionError", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("ErrorTime") + .HasColumnType("datetime(6)"); + + b.Property("ExecutionPointerId") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("WorkflowId") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("PersistenceId"); + + b.ToTable("ExecutionError"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Children") + .HasColumnType("longtext"); + + b.Property("ContextItem") + .HasColumnType("longtext"); + + b.Property("EndTime") + .HasColumnType("datetime(6)"); + + b.Property("EventData") + .HasColumnType("longtext"); + + b.Property("EventKey") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("EventName") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("EventPublished") + .HasColumnType("tinyint(1)"); + + b.Property("Id") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Outcome") + .HasColumnType("longtext"); + + b.Property("PersistenceData") + .HasColumnType("longtext"); + + b.Property("PredecessorId") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Scope") + .HasColumnType("longtext"); + + b.Property("SleepUntil") + .HasColumnType("datetime(6)"); + + b.Property("StartTime") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("StepId") + .HasColumnType("int"); + + b.Property("StepName") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("WorkflowId") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("WorkflowId"); + + b.ToTable("ExecutionPointer"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("AttributeKey") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("AttributeValue") + .HasColumnType("longtext"); + + b.Property("ExecutionPointerId") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecutionPointerId"); + + b.ToTable("ExtensionAttribute"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedScheduledCommand", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CommandName") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Data") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("ExecuteTime") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecuteTime"); + + b.HasIndex("CommandName", "Data") + .IsUnique(); + + b.ToTable("PersistedScheduledCommand"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ExecutionPointerId") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ExternalToken") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ExternalTokenExpiry") + .HasColumnType("datetime(6)"); + + b.Property("ExternalWorkerId") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("StepId") + .HasColumnType("int"); + + b.Property("SubscribeAsOf") + .HasColumnType("datetime(6)"); + + b.Property("SubscriptionData") + .HasColumnType("longtext"); + + b.Property("SubscriptionId") + .HasMaxLength(200) + .HasColumnType("char(200)"); + + b.Property("WorkflowId") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventKey"); + + b.HasIndex("EventName"); + + b.HasIndex("SubscriptionId") + .IsUnique(); + + b.ToTable("Subscription"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CompleteTime") + .HasColumnType("datetime(6)"); + + b.Property("CreateTime") + .HasColumnType("datetime(6)"); + + b.Property("Data") + .HasColumnType("longtext"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("InstanceId") + .HasMaxLength(200) + .HasColumnType("char(200)"); + + b.Property("NextExecution") + .HasColumnType("bigint"); + + b.Property("Reference") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Version") + .HasColumnType("int"); + + b.Property("WorkflowDefinitionId") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("InstanceId") + .IsUnique(); + + b.HasIndex("NextExecution"); + + b.ToTable("Workflow"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", "Workflow") + .WithMany("ExecutionPointers") + .HasForeignKey("WorkflowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Workflow"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", "ExecutionPointer") + .WithMany("ExtensionAttributes") + .HasForeignKey("ExecutionPointerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ExecutionPointer"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Navigation("ExtensionAttributes"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Navigation("ExecutionPointers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211015215708_scheduled-commands.cs b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211015215708_scheduled-commands.cs new file mode 100644 index 000000000..b08be15b8 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211015215708_scheduled-commands.cs @@ -0,0 +1,337 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace WorkflowCore.Persistence.MySQL.Migrations +{ + public partial class scheduledcommands : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "InstanceId", + table: "Workflow", + type: "char(200)", + maxLength: 200, + nullable: false, + collation: "ascii_general_ci", + oldClrType: typeof(string), + oldType: "char(200)", + oldMaxLength: 200) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Data", + table: "Workflow", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "SubscriptionId", + table: "Subscription", + type: "char(200)", + maxLength: 200, + nullable: false, + collation: "ascii_general_ci", + oldClrType: typeof(string), + oldType: "char(200)", + oldMaxLength: 200) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "SubscriptionData", + table: "Subscription", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "AttributeValue", + table: "ExtensionAttribute", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Scope", + table: "ExecutionPointer", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "PersistenceData", + table: "ExecutionPointer", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Outcome", + table: "ExecutionPointer", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "EventData", + table: "ExecutionPointer", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ContextItem", + table: "ExecutionPointer", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Children", + table: "ExecutionPointer", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Message", + table: "ExecutionError", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "EventData", + table: "Event", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "PersistedScheduledCommand", + columns: table => new + { + PersistenceId = table.Column(type: "bigint", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CommandName = table.Column(type: "varchar(200)", maxLength: 200, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Data = table.Column(type: "varchar(500)", maxLength: 500, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ExecuteTime = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PersistedScheduledCommand", x => x.PersistenceId); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedScheduledCommand_CommandName_Data", + table: "PersistedScheduledCommand", + columns: new[] { "CommandName", "Data" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_PersistedScheduledCommand_ExecuteTime", + table: "PersistedScheduledCommand", + column: "ExecuteTime"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "PersistedScheduledCommand"); + + migrationBuilder.AlterColumn( + name: "InstanceId", + table: "Workflow", + type: "char(200)", + maxLength: 200, + nullable: false, + oldClrType: typeof(Guid), + oldType: "char(200)", + oldMaxLength: 200) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("Relational:Collation", "ascii_general_ci"); + + migrationBuilder.AlterColumn( + name: "Data", + table: "Workflow", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "SubscriptionId", + table: "Subscription", + type: "char(200)", + maxLength: 200, + nullable: false, + oldClrType: typeof(Guid), + oldType: "char(200)", + oldMaxLength: 200) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("Relational:Collation", "ascii_general_ci"); + + migrationBuilder.AlterColumn( + name: "SubscriptionData", + table: "Subscription", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "AttributeValue", + table: "ExtensionAttribute", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Scope", + table: "ExecutionPointer", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "PersistenceData", + table: "ExecutionPointer", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Outcome", + table: "ExecutionPointer", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "EventData", + table: "ExecutionPointer", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ContextItem", + table: "ExecutionPointer", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Children", + table: "ExecutionPointer", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Message", + table: "ExecutionError", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "EventData", + table: "Event", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs index c72c16199..cd2b9ceeb 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs @@ -2,6 +2,8 @@ using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using WorkflowCore.Persistence.MySQL; namespace WorkflowCore.Persistence.MySQL.Migrations { @@ -12,8 +14,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.2") - .HasAnnotation("Relational:MaxIdentifierLength", 64); + .HasAnnotation("Relational:MaxIdentifierLength", 64) + .HasAnnotation("ProductVersion", "5.0.8"); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => { @@ -22,18 +24,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("bigint"); b.Property("EventData") - .HasColumnType("longtext CHARACTER SET utf8mb4"); + .HasColumnType("longtext"); b.Property("EventId") .HasColumnType("char(36)"); b.Property("EventKey") - .HasColumnType("varchar(200) CHARACTER SET utf8mb4") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("varchar(200)"); b.Property("EventName") - .HasColumnType("varchar(200) CHARACTER SET utf8mb4") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("varchar(200)"); b.Property("EventTime") .HasColumnType("datetime(6)"); @@ -65,15 +67,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("datetime(6)"); b.Property("ExecutionPointerId") - .HasColumnType("varchar(100) CHARACTER SET utf8mb4") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("varchar(100)"); b.Property("Message") - .HasColumnType("longtext CHARACTER SET utf8mb4"); + .HasColumnType("longtext"); b.Property("WorkflowId") - .HasColumnType("varchar(100) CHARACTER SET utf8mb4") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("varchar(100)"); b.HasKey("PersistenceId"); @@ -90,47 +92,47 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("tinyint(1)"); b.Property("Children") - .HasColumnType("longtext CHARACTER SET utf8mb4"); + .HasColumnType("longtext"); b.Property("ContextItem") - .HasColumnType("longtext CHARACTER SET utf8mb4"); + .HasColumnType("longtext"); b.Property("EndTime") .HasColumnType("datetime(6)"); b.Property("EventData") - .HasColumnType("longtext CHARACTER SET utf8mb4"); + .HasColumnType("longtext"); b.Property("EventKey") - .HasColumnType("varchar(100) CHARACTER SET utf8mb4") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("varchar(100)"); b.Property("EventName") - .HasColumnType("varchar(100) CHARACTER SET utf8mb4") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("varchar(100)"); b.Property("EventPublished") .HasColumnType("tinyint(1)"); b.Property("Id") - .HasColumnType("varchar(50) CHARACTER SET utf8mb4") - .HasMaxLength(50); + .HasMaxLength(50) + .HasColumnType("varchar(50)"); b.Property("Outcome") - .HasColumnType("longtext CHARACTER SET utf8mb4"); + .HasColumnType("longtext"); b.Property("PersistenceData") - .HasColumnType("longtext CHARACTER SET utf8mb4"); + .HasColumnType("longtext"); b.Property("PredecessorId") - .HasColumnType("varchar(100) CHARACTER SET utf8mb4") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("varchar(100)"); b.Property("RetryCount") .HasColumnType("int"); b.Property("Scope") - .HasColumnType("longtext CHARACTER SET utf8mb4"); + .HasColumnType("longtext"); b.Property("SleepUntil") .HasColumnType("datetime(6)"); @@ -145,8 +147,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("int"); b.Property("StepName") - .HasColumnType("varchar(100) CHARACTER SET utf8mb4") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("varchar(100)"); b.Property("WorkflowId") .HasColumnType("bigint"); @@ -165,11 +167,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("bigint"); b.Property("AttributeKey") - .HasColumnType("varchar(100) CHARACTER SET utf8mb4") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("varchar(100)"); b.Property("AttributeValue") - .HasColumnType("longtext CHARACTER SET utf8mb4"); + .HasColumnType("longtext"); b.Property("ExecutionPointerId") .HasColumnType("bigint"); @@ -181,6 +183,33 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ExtensionAttribute"); }); + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedScheduledCommand", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CommandName") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Data") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("ExecuteTime") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecuteTime"); + + b.HasIndex("CommandName", "Data") + .IsUnique(); + + b.ToTable("PersistedScheduledCommand"); + }); + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => { b.Property("PersistenceId") @@ -188,27 +217,27 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("bigint"); b.Property("EventKey") - .HasColumnType("varchar(200) CHARACTER SET utf8mb4") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("varchar(200)"); b.Property("EventName") - .HasColumnType("varchar(200) CHARACTER SET utf8mb4") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("varchar(200)"); b.Property("ExecutionPointerId") - .HasColumnType("varchar(200) CHARACTER SET utf8mb4") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("varchar(200)"); b.Property("ExternalToken") - .HasColumnType("varchar(200) CHARACTER SET utf8mb4") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("varchar(200)"); b.Property("ExternalTokenExpiry") .HasColumnType("datetime(6)"); b.Property("ExternalWorkerId") - .HasColumnType("varchar(200) CHARACTER SET utf8mb4") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("varchar(200)"); b.Property("StepId") .HasColumnType("int"); @@ -217,15 +246,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("datetime(6)"); b.Property("SubscriptionData") - .HasColumnType("longtext CHARACTER SET utf8mb4"); + .HasColumnType("longtext"); b.Property("SubscriptionId") - .HasColumnType("char(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("char(200)"); b.Property("WorkflowId") - .HasColumnType("varchar(200) CHARACTER SET utf8mb4") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("varchar(200)"); b.HasKey("PersistenceId"); @@ -252,22 +281,22 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("datetime(6)"); b.Property("Data") - .HasColumnType("longtext CHARACTER SET utf8mb4"); + .HasColumnType("longtext"); b.Property("Description") - .HasColumnType("varchar(500) CHARACTER SET utf8mb4") - .HasMaxLength(500); + .HasMaxLength(500) + .HasColumnType("varchar(500)"); b.Property("InstanceId") - .HasColumnType("char(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("char(200)"); b.Property("NextExecution") .HasColumnType("bigint"); b.Property("Reference") - .HasColumnType("varchar(200) CHARACTER SET utf8mb4") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("varchar(200)"); b.Property("Status") .HasColumnType("int"); @@ -276,8 +305,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("int"); b.Property("WorkflowDefinitionId") - .HasColumnType("varchar(200) CHARACTER SET utf8mb4") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("varchar(200)"); b.HasKey("PersistenceId"); @@ -296,6 +325,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("WorkflowId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + + b.Navigation("Workflow"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => @@ -305,6 +336,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("ExecutionPointerId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + + b.Navigation("ExecutionPointer"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Navigation("ExtensionAttributes"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Navigation("ExecutionPointers"); }); #pragma warning restore 612, 618 } diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index e0e83315b..1b2fa9f6b 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -4,7 +4,7 @@ Workflow Core MySQL Persistence Provider 1.0.0 Daniel Gerlag - netstandard2.0;netstandard2.1 + netstandard2.1 WorkflowCore.Persistence.MySQL WorkflowCore.Persistence.MySQL workflow;.NET;Core;state machine;WorkflowCore;MySQL diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211015204734_scheduled-commands.Designer.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211015204734_scheduled-commands.Designer.cs new file mode 100644 index 000000000..caa2f0941 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211015204734_scheduled-commands.Designer.cs @@ -0,0 +1,366 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using WorkflowCore.Persistence.PostgreSQL; + +namespace WorkflowCore.Persistence.PostgreSQL.Migrations +{ + [DbContext(typeof(PostgresContext))] + [Migration("20211015204734_scheduled-commands")] + partial class scheduledcommands + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 63) + .HasAnnotation("ProductVersion", "5.0.8") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("EventData") + .HasColumnType("text"); + + b.Property("EventId") + .HasColumnType("uuid"); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EventTime") + .HasColumnType("timestamp without time zone"); + + b.Property("IsProcessed") + .HasColumnType("boolean"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventId") + .IsUnique(); + + b.HasIndex("EventTime"); + + b.HasIndex("IsProcessed"); + + b.HasIndex("EventName", "EventKey"); + + b.ToTable("Event", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionError", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("ErrorTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExecutionPointerId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("WorkflowId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("PersistenceId"); + + b.ToTable("ExecutionError", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("Children") + .HasColumnType("text"); + + b.Property("ContextItem") + .HasColumnType("text"); + + b.Property("EndTime") + .HasColumnType("timestamp without time zone"); + + b.Property("EventData") + .HasColumnType("text"); + + b.Property("EventKey") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EventName") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EventPublished") + .HasColumnType("boolean"); + + b.Property("Id") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Outcome") + .HasColumnType("text"); + + b.Property("PersistenceData") + .HasColumnType("text"); + + b.Property("PredecessorId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RetryCount") + .HasColumnType("integer"); + + b.Property("Scope") + .HasColumnType("text"); + + b.Property("SleepUntil") + .HasColumnType("timestamp without time zone"); + + b.Property("StartTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("StepId") + .HasColumnType("integer"); + + b.Property("StepName") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("WorkflowId") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("WorkflowId"); + + b.ToTable("ExecutionPointer", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("AttributeKey") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("AttributeValue") + .HasColumnType("text"); + + b.Property("ExecutionPointerId") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecutionPointerId"); + + b.ToTable("ExtensionAttribute", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedScheduledCommand", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("CommandName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Data") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ExecuteTime") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecuteTime"); + + b.HasIndex("CommandName", "Data") + .IsUnique(); + + b.ToTable("PersistedScheduledCommand"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ExecutionPointerId") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ExternalToken") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ExternalTokenExpiry") + .HasColumnType("timestamp without time zone"); + + b.Property("ExternalWorkerId") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("StepId") + .HasColumnType("integer"); + + b.Property("SubscribeAsOf") + .HasColumnType("timestamp without time zone"); + + b.Property("SubscriptionData") + .HasColumnType("text"); + + b.Property("SubscriptionId") + .HasMaxLength(200) + .HasColumnType("uuid"); + + b.Property("WorkflowId") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventKey"); + + b.HasIndex("EventName"); + + b.HasIndex("SubscriptionId") + .IsUnique(); + + b.ToTable("Subscription", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("CompleteTime") + .HasColumnType("timestamp without time zone"); + + b.Property("CreateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("InstanceId") + .HasMaxLength(200) + .HasColumnType("uuid"); + + b.Property("NextExecution") + .HasColumnType("bigint"); + + b.Property("Reference") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Version") + .HasColumnType("integer"); + + b.Property("WorkflowDefinitionId") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("InstanceId") + .IsUnique(); + + b.HasIndex("NextExecution"); + + b.ToTable("Workflow", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", "Workflow") + .WithMany("ExecutionPointers") + .HasForeignKey("WorkflowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Workflow"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", "ExecutionPointer") + .WithMany("ExtensionAttributes") + .HasForeignKey("ExecutionPointerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ExecutionPointer"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Navigation("ExtensionAttributes"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Navigation("ExecutionPointers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211015204734_scheduled-commands.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211015204734_scheduled-commands.cs new file mode 100644 index 000000000..23eff0eb2 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211015204734_scheduled-commands.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace WorkflowCore.Persistence.PostgreSQL.Migrations +{ + public partial class scheduledcommands : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "PersistedScheduledCommand", + columns: table => new + { + PersistenceId = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + CommandName = table.Column(type: "character varying(200)", maxLength: 200, nullable: true), + Data = table.Column(type: "character varying(500)", maxLength: 500, nullable: true), + ExecuteTime = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PersistedScheduledCommand", x => x.PersistenceId); + }); + + migrationBuilder.CreateIndex( + name: "IX_PersistedScheduledCommand_CommandName_Data", + table: "PersistedScheduledCommand", + columns: new[] { "CommandName", "Data" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_PersistedScheduledCommand_ExecuteTime", + table: "PersistedScheduledCommand", + column: "ExecuteTime"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "PersistedScheduledCommand"); + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs index 6def22497..76c681d8d 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs @@ -2,7 +2,9 @@ using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using WorkflowCore.Persistence.PostgreSQL; namespace WorkflowCore.Persistence.PostgreSQL.Migrations { @@ -13,9 +15,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) - .HasAnnotation("ProductVersion", "3.1.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); + .HasAnnotation("Relational:MaxIdentifierLength", 63) + .HasAnnotation("ProductVersion", "5.0.8") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => { @@ -31,12 +33,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid"); b.Property("EventKey") - .HasColumnType("character varying(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("character varying(200)"); b.Property("EventName") - .HasColumnType("character varying(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("character varying(200)"); b.Property("EventTime") .HasColumnType("timestamp without time zone"); @@ -55,7 +57,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventName", "EventKey"); - b.ToTable("Event","wfc"); + b.ToTable("Event", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionError", b => @@ -69,19 +71,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("timestamp without time zone"); b.Property("ExecutionPointerId") - .HasColumnType("character varying(100)") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("character varying(100)"); b.Property("Message") .HasColumnType("text"); b.Property("WorkflowId") - .HasColumnType("character varying(100)") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("character varying(100)"); b.HasKey("PersistenceId"); - b.ToTable("ExecutionError","wfc"); + b.ToTable("ExecutionError", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => @@ -107,19 +109,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text"); b.Property("EventKey") - .HasColumnType("character varying(100)") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("character varying(100)"); b.Property("EventName") - .HasColumnType("character varying(100)") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("character varying(100)"); b.Property("EventPublished") .HasColumnType("boolean"); b.Property("Id") - .HasColumnType("character varying(50)") - .HasMaxLength(50); + .HasMaxLength(50) + .HasColumnType("character varying(50)"); b.Property("Outcome") .HasColumnType("text"); @@ -128,8 +130,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text"); b.Property("PredecessorId") - .HasColumnType("character varying(100)") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("character varying(100)"); b.Property("RetryCount") .HasColumnType("integer"); @@ -150,8 +152,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("integer"); b.Property("StepName") - .HasColumnType("character varying(100)") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("character varying(100)"); b.Property("WorkflowId") .HasColumnType("bigint"); @@ -160,7 +162,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("WorkflowId"); - b.ToTable("ExecutionPointer","wfc"); + b.ToTable("ExecutionPointer", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => @@ -171,8 +173,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("AttributeKey") - .HasColumnType("character varying(100)") - .HasMaxLength(100); + .HasMaxLength(100) + .HasColumnType("character varying(100)"); b.Property("AttributeValue") .HasColumnType("text"); @@ -184,7 +186,35 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ExecutionPointerId"); - b.ToTable("ExtensionAttribute","wfc"); + b.ToTable("ExtensionAttribute", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedScheduledCommand", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("CommandName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Data") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ExecuteTime") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecuteTime"); + + b.HasIndex("CommandName", "Data") + .IsUnique(); + + b.ToTable("PersistedScheduledCommand"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => @@ -195,27 +225,27 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("EventKey") - .HasColumnType("character varying(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("character varying(200)"); b.Property("EventName") - .HasColumnType("character varying(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("character varying(200)"); b.Property("ExecutionPointerId") - .HasColumnType("character varying(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("character varying(200)"); b.Property("ExternalToken") - .HasColumnType("character varying(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("character varying(200)"); b.Property("ExternalTokenExpiry") .HasColumnType("timestamp without time zone"); b.Property("ExternalWorkerId") - .HasColumnType("character varying(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("character varying(200)"); b.Property("StepId") .HasColumnType("integer"); @@ -227,12 +257,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text"); b.Property("SubscriptionId") - .HasColumnType("uuid") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("uuid"); b.Property("WorkflowId") - .HasColumnType("character varying(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("character varying(200)"); b.HasKey("PersistenceId"); @@ -243,7 +273,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("SubscriptionId") .IsUnique(); - b.ToTable("Subscription","wfc"); + b.ToTable("Subscription", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => @@ -263,19 +293,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text"); b.Property("Description") - .HasColumnType("character varying(500)") - .HasMaxLength(500); + .HasMaxLength(500) + .HasColumnType("character varying(500)"); b.Property("InstanceId") - .HasColumnType("uuid") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("uuid"); b.Property("NextExecution") .HasColumnType("bigint"); b.Property("Reference") - .HasColumnType("character varying(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("character varying(200)"); b.Property("Status") .HasColumnType("integer"); @@ -284,8 +314,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("integer"); b.Property("WorkflowDefinitionId") - .HasColumnType("character varying(200)") - .HasMaxLength(200); + .HasMaxLength(200) + .HasColumnType("character varying(200)"); b.HasKey("PersistenceId"); @@ -294,7 +324,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("NextExecution"); - b.ToTable("Workflow","wfc"); + b.ToTable("Workflow", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => @@ -304,6 +334,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("WorkflowId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + + b.Navigation("Workflow"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => @@ -313,6 +345,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("ExecutionPointerId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + + b.Navigation("ExecutionPointer"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Navigation("ExtensionAttributes"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Navigation("ExecutionPointers"); }); #pragma warning restore 612, 618 } diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211015215114_scheduled-commands.Designer.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211015215114_scheduled-commands.Designer.cs new file mode 100644 index 000000000..489276722 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211015215114_scheduled-commands.Designer.cs @@ -0,0 +1,379 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using WorkflowCore.Persistence.SqlServer; + +namespace WorkflowCore.Persistence.SqlServer.Migrations +{ + [DbContext(typeof(SqlServerContext))] + [Migration("20211015215114_scheduled-commands")] + partial class scheduledcommands + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.8") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("SqlServer:IdentityIncrement", 1) + .HasAnnotation("SqlServer:IdentitySeed", 1) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("EventData") + .HasColumnType("nvarchar(max)"); + + b.Property("EventId") + .HasColumnType("uniqueidentifier"); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("EventTime") + .HasColumnType("datetime2"); + + b.Property("IsProcessed") + .HasColumnType("bit"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventId") + .IsUnique(); + + b.HasIndex("EventTime"); + + b.HasIndex("IsProcessed"); + + b.HasIndex("EventName", "EventKey"); + + b.ToTable("Event", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionError", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("SqlServer:IdentityIncrement", 1) + .HasAnnotation("SqlServer:IdentitySeed", 1) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ErrorTime") + .HasColumnType("datetime2"); + + b.Property("ExecutionPointerId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Message") + .HasColumnType("nvarchar(max)"); + + b.Property("WorkflowId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("PersistenceId"); + + b.ToTable("ExecutionError", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("SqlServer:IdentityIncrement", 1) + .HasAnnotation("SqlServer:IdentitySeed", 1) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("Active") + .HasColumnType("bit"); + + b.Property("Children") + .HasColumnType("nvarchar(max)"); + + b.Property("ContextItem") + .HasColumnType("nvarchar(max)"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("EventData") + .HasColumnType("nvarchar(max)"); + + b.Property("EventKey") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("EventName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("EventPublished") + .HasColumnType("bit"); + + b.Property("Id") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Outcome") + .HasColumnType("nvarchar(max)"); + + b.Property("PersistenceData") + .HasColumnType("nvarchar(max)"); + + b.Property("PredecessorId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Scope") + .HasColumnType("nvarchar(max)"); + + b.Property("SleepUntil") + .HasColumnType("datetime2"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("StepId") + .HasColumnType("int"); + + b.Property("StepName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("WorkflowId") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("WorkflowId"); + + b.ToTable("ExecutionPointer", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("SqlServer:IdentityIncrement", 1) + .HasAnnotation("SqlServer:IdentitySeed", 1) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("AttributeKey") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("AttributeValue") + .HasColumnType("nvarchar(max)"); + + b.Property("ExecutionPointerId") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecutionPointerId"); + + b.ToTable("ExtensionAttribute", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedScheduledCommand", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CommandName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Data") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("ExecuteTime") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecuteTime"); + + b.HasIndex("CommandName", "Data") + .IsUnique() + .HasFilter("[CommandName] IS NOT NULL AND [Data] IS NOT NULL"); + + b.ToTable("PersistedScheduledCommand"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("SqlServer:IdentityIncrement", 1) + .HasAnnotation("SqlServer:IdentitySeed", 1) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ExecutionPointerId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ExternalToken") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ExternalTokenExpiry") + .HasColumnType("datetime2"); + + b.Property("ExternalWorkerId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("StepId") + .HasColumnType("int"); + + b.Property("SubscribeAsOf") + .HasColumnType("datetime2"); + + b.Property("SubscriptionData") + .HasColumnType("nvarchar(max)"); + + b.Property("SubscriptionId") + .HasMaxLength(200) + .HasColumnType("uniqueidentifier"); + + b.Property("WorkflowId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventKey"); + + b.HasIndex("EventName"); + + b.HasIndex("SubscriptionId") + .IsUnique(); + + b.ToTable("Subscription", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("SqlServer:IdentityIncrement", 1) + .HasAnnotation("SqlServer:IdentitySeed", 1) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CompleteTime") + .HasColumnType("datetime2"); + + b.Property("CreateTime") + .HasColumnType("datetime2"); + + b.Property("Data") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("InstanceId") + .HasMaxLength(200) + .HasColumnType("uniqueidentifier"); + + b.Property("NextExecution") + .HasColumnType("bigint"); + + b.Property("Reference") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Version") + .HasColumnType("int"); + + b.Property("WorkflowDefinitionId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("InstanceId") + .IsUnique(); + + b.HasIndex("NextExecution"); + + b.ToTable("Workflow", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", "Workflow") + .WithMany("ExecutionPointers") + .HasForeignKey("WorkflowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Workflow"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", "ExecutionPointer") + .WithMany("ExtensionAttributes") + .HasForeignKey("ExecutionPointerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ExecutionPointer"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Navigation("ExtensionAttributes"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Navigation("ExecutionPointers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211015215114_scheduled-commands.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211015215114_scheduled-commands.cs new file mode 100644 index 000000000..357fbe2f1 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211015215114_scheduled-commands.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace WorkflowCore.Persistence.SqlServer.Migrations +{ + public partial class scheduledcommands : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "PersistedScheduledCommand", + columns: table => new + { + PersistenceId = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + CommandName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Data = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: true), + ExecuteTime = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PersistedScheduledCommand", x => x.PersistenceId); + }); + + migrationBuilder.CreateIndex( + name: "IX_PersistedScheduledCommand_CommandName_Data", + table: "PersistedScheduledCommand", + columns: new[] { "CommandName", "Data" }, + unique: true, + filter: "[CommandName] IS NOT NULL AND [Data] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedScheduledCommand_ExecuteTime", + table: "PersistedScheduledCommand", + column: "ExecuteTime"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "PersistedScheduledCommand"); + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs index 2e32d838d..df593d220 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs @@ -2,6 +2,9 @@ using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using WorkflowCore.Persistence.SqlServer; namespace WorkflowCore.Persistence.SqlServer.Migrations { @@ -12,16 +15,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .UseIdentityColumns() .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.1"); + .HasAnnotation("ProductVersion", "5.0.8") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => { b.Property("PersistenceId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:IdentityIncrement", 1) + .HasAnnotation("SqlServer:IdentitySeed", 1) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("EventData") .HasColumnType("nvarchar(max)"); @@ -62,7 +67,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PersistenceId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:IdentityIncrement", 1) + .HasAnnotation("SqlServer:IdentitySeed", 1) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ErrorTime") .HasColumnType("datetime2"); @@ -88,7 +95,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PersistenceId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:IdentityIncrement", 1) + .HasAnnotation("SqlServer:IdentitySeed", 1) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Active") .HasColumnType("bit"); @@ -167,7 +176,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PersistenceId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:IdentityIncrement", 1) + .HasAnnotation("SqlServer:IdentitySeed", 1) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("AttributeKey") .HasMaxLength(100) @@ -186,12 +197,43 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ExtensionAttribute", "wfc"); }); + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedScheduledCommand", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CommandName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Data") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("ExecuteTime") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecuteTime"); + + b.HasIndex("CommandName", "Data") + .IsUnique() + .HasFilter("[CommandName] IS NOT NULL AND [Data] IS NOT NULL"); + + b.ToTable("PersistedScheduledCommand"); + }); + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => { b.Property("PersistenceId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:IdentityIncrement", 1) + .HasAnnotation("SqlServer:IdentitySeed", 1) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("EventKey") .HasMaxLength(200) @@ -250,7 +292,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PersistenceId") .ValueGeneratedOnAdd() .HasColumnType("bigint") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:IdentityIncrement", 1) + .HasAnnotation("SqlServer:IdentitySeed", 1) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("CompleteTime") .HasColumnType("datetime2"); diff --git a/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlDelayScenario.cs b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlDelayScenario.cs new file mode 100644 index 000000000..deed80f2b --- /dev/null +++ b/test/WorkflowCore.Tests.MySQL/Scenarios/MysqlDelayScenario.cs @@ -0,0 +1,20 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using WorkflowCore.IntegrationTests.Scenarios; +using Xunit; + +namespace WorkflowCore.Tests.MySQL.Scenarios +{ + [Collection("Mysql collection")] + public class MysqlDelayScenario : DelayScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(cfg => + { + cfg.UseMySQL(MysqlDockerSetup.ScenarioConnectionString, true, true); + cfg.UsePollInterval(TimeSpan.FromSeconds(2)); + }); + } + } +} From 94e70d70d2903e37378e3c3eb95c1e2e1e3db4ef Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 22 Oct 2021 19:04:18 -0700 Subject: [PATCH 182/342] release notes --- ReleaseNotes/3.7.0.md | 8 ++++++++ WorkflowCore.sln | 2 ++ 2 files changed, 10 insertions(+) create mode 100644 ReleaseNotes/3.7.0.md diff --git a/ReleaseNotes/3.7.0.md b/ReleaseNotes/3.7.0.md new file mode 100644 index 000000000..a6a8ec126 --- /dev/null +++ b/ReleaseNotes/3.7.0.md @@ -0,0 +1,8 @@ +# Workflow Core 3.7.0 + +## Scheduled Commands + +Introduces the ability to schedule delayed commands to process a workflow or event, by persisting them to storage. +This is the first step toward removing constant polling of the DB. It also filters out duplicate work items on the queue which is the current problem the greylist tries to solve. +Initial implementation is supported by MongoDb, SQL Server, PostgeSQL, MySQL and SQLite. +Additional support from the other persistence providers to follow. diff --git a/WorkflowCore.sln b/WorkflowCore.sln index 5893af37d..cf389574e 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -104,6 +104,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReleaseNotes", "ReleaseNote ReleaseNotes\3.0.0.md = ReleaseNotes\3.0.0.md ReleaseNotes\3.1.0.md = ReleaseNotes\3.1.0.md ReleaseNotes\3.3.0.md = ReleaseNotes\3.3.0.md + ReleaseNotes\3.4.0.md = ReleaseNotes\3.4.0.md + ReleaseNotes\3.7.0.md = ReleaseNotes\3.7.0.md EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample14", "src\samples\WorkflowCore.Sample14\WorkflowCore.Sample14.csproj", "{6BC66637-B42A-4334-ADFB-DBEC9F29D293}" From b34690c5142c0f5bc86f50e0c97c4e41d7bbb72d Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 22 Oct 2021 19:19:42 -0700 Subject: [PATCH 183/342] bug --- .../Services/EntityFrameworkPersistenceProvider.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs index 56dd7f90c..44798a0c9 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs @@ -398,8 +398,9 @@ public async Task ProcessCommands(DateTimeOffset asOf, Func().Remove(command); - await db.SaveChangesAsync(); + using var db2 = ConstructDbContext(); + db2.Set().Remove(command); + await db2.SaveChangesAsync(); } catch (Exception) { From c42313c90fa859ab43628ed15de39c14a0bb9fb3 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 23 Oct 2021 09:09:03 -0700 Subject: [PATCH 184/342] table name --- .../Services/WorkflowDbContext.cs | 2 ++ .../WorkflowCore.Persistence.MySQL/MysqlContext.cs | 6 ++++++ .../WorkflowCore.Persistence.PostgreSQL/PostgresContext.cs | 6 ++++++ .../WorkflowCore.Persistence.SqlServer/SqlServerContext.cs | 6 ++++++ .../WorkflowCore.Persistence.Sqlite/SqliteContext.cs | 5 +++++ 5 files changed, 25 insertions(+) diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs index 645a26c3d..53e0967e7 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs @@ -14,6 +14,7 @@ public abstract class WorkflowDbContext : DbContext protected abstract void ConfigureExetensionAttributeStorage(EntityTypeBuilder builder); protected abstract void ConfigureSubscriptionStorage(EntityTypeBuilder builder); protected abstract void ConfigureEventStorage(EntityTypeBuilder builder); + protected abstract void ConfigureScheduledCommandStorage(EntityTypeBuilder builder); protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -48,6 +49,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) ConfigureExetensionAttributeStorage(extensionAttributes); ConfigureSubscriptionStorage(subscriptions); ConfigureEventStorage(events); + ConfigureScheduledCommandStorage(commands); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) diff --git a/src/providers/WorkflowCore.Persistence.MySQL/MysqlContext.cs b/src/providers/WorkflowCore.Persistence.MySQL/MysqlContext.cs index a6ebba9c2..dc49617fd 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/MysqlContext.cs +++ b/src/providers/WorkflowCore.Persistence.MySQL/MysqlContext.cs @@ -63,5 +63,11 @@ protected override void ConfigureEventStorage(EntityTypeBuilder builder.ToTable("Event"); builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); } + + protected override void ConfigureScheduledCommandStorage(EntityTypeBuilder builder) + { + builder.ToTable("ScheduledCommand"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } } } diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContext.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContext.cs index 17e83e958..3eb80b448 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContext.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContext.cs @@ -60,6 +60,12 @@ protected override void ConfigureEventStorage(EntityTypeBuilder builder.ToTable("Event", _schemaName); builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); } + + protected override void ConfigureScheduledCommandStorage(EntityTypeBuilder builder) + { + builder.ToTable("ScheduledCommand", _schemaName); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } } } diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs b/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs index 6e2656a5b..eb03f3647 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/SqlServerContext.cs @@ -58,5 +58,11 @@ protected override void ConfigureEventStorage(EntityTypeBuilder builder.ToTable("Event", "wfc"); builder.Property(x => x.PersistenceId).UseIdentityColumn(); } + + protected override void ConfigureScheduledCommandStorage(EntityTypeBuilder builder) + { + builder.ToTable("ScheduledCommand", "wfc"); + builder.Property(x => x.PersistenceId).UseIdentityColumn(); + } } } diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/SqliteContext.cs b/src/providers/WorkflowCore.Persistence.Sqlite/SqliteContext.cs index 1b5a6c469..0f2083933 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/SqliteContext.cs +++ b/src/providers/WorkflowCore.Persistence.Sqlite/SqliteContext.cs @@ -52,5 +52,10 @@ protected override void ConfigureEventStorage(EntityTypeBuilder { builder.ToTable("Event"); } + + protected override void ConfigureScheduledCommandStorage(EntityTypeBuilder builder) + { + builder.ToTable("ScheduledCommand"); + } } } From 74e046767ba6f668818c2a81d5f31a12929957ff Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 23 Oct 2021 09:21:35 -0700 Subject: [PATCH 185/342] migration --- ...11023161949_scheduled-commands.Designer.cs} | 4 ++-- ...cs => 20211023161949_scheduled-commands.cs} | 14 +++++++------- .../MysqlPersistenceProviderModelSnapshot.cs | 2 +- ...11023161649_scheduled-commands.Designer.cs} | 4 ++-- ...cs => 20211023161649_scheduled-commands.cs} | 18 +++++++++++------- ...PostgresPersistenceProviderModelSnapshot.cs | 2 +- ...11023161544_scheduled-commands.Designer.cs} | 6 ++++-- ...cs => 20211023161544_scheduled-commands.cs} | 18 +++++++++++------- ...qlServerPersistenceProviderModelSnapshot.cs | 4 +++- 9 files changed, 42 insertions(+), 30 deletions(-) rename src/providers/WorkflowCore.Persistence.MySQL/Migrations/{20211015215708_scheduled-commands.Designer.cs => 20211023161949_scheduled-commands.Designer.cs} (99%) rename src/providers/WorkflowCore.Persistence.MySQL/Migrations/{20211015215708_scheduled-commands.cs => 20211023161949_scheduled-commands.cs} (96%) rename src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/{20211015204734_scheduled-commands.Designer.cs => 20211023161649_scheduled-commands.Designer.cs} (99%) rename src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/{20211015204734_scheduled-commands.cs => 20211023161649_scheduled-commands.cs} (73%) rename src/providers/WorkflowCore.Persistence.SqlServer/Migrations/{20211015215114_scheduled-commands.Designer.cs => 20211023161544_scheduled-commands.Designer.cs} (98%) rename src/providers/WorkflowCore.Persistence.SqlServer/Migrations/{20211015215114_scheduled-commands.cs => 20211023161544_scheduled-commands.cs} (72%) diff --git a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211015215708_scheduled-commands.Designer.cs b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211023161949_scheduled-commands.Designer.cs similarity index 99% rename from src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211015215708_scheduled-commands.Designer.cs rename to src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211023161949_scheduled-commands.Designer.cs index 9573baf3e..94222e8d5 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211015215708_scheduled-commands.Designer.cs +++ b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211023161949_scheduled-commands.Designer.cs @@ -9,7 +9,7 @@ namespace WorkflowCore.Persistence.MySQL.Migrations { [DbContext(typeof(MysqlContext))] - [Migration("20211015215708_scheduled-commands")] + [Migration("20211023161949_scheduled-commands")] partial class scheduledcommands { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -209,7 +209,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("CommandName", "Data") .IsUnique(); - b.ToTable("PersistedScheduledCommand"); + b.ToTable("ScheduledCommand"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => diff --git a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211015215708_scheduled-commands.cs b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211023161949_scheduled-commands.cs similarity index 96% rename from src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211015215708_scheduled-commands.cs rename to src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211023161949_scheduled-commands.cs index b08be15b8..b06303070 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211015215708_scheduled-commands.cs +++ b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/20211023161949_scheduled-commands.cs @@ -154,7 +154,7 @@ protected override void Up(MigrationBuilder migrationBuilder) .OldAnnotation("MySql:CharSet", "utf8mb4"); migrationBuilder.CreateTable( - name: "PersistedScheduledCommand", + name: "ScheduledCommand", columns: table => new { PersistenceId = table.Column(type: "bigint", nullable: false) @@ -167,26 +167,26 @@ protected override void Up(MigrationBuilder migrationBuilder) }, constraints: table => { - table.PrimaryKey("PK_PersistedScheduledCommand", x => x.PersistenceId); + table.PrimaryKey("PK_ScheduledCommand", x => x.PersistenceId); }) .Annotation("MySql:CharSet", "utf8mb4"); migrationBuilder.CreateIndex( - name: "IX_PersistedScheduledCommand_CommandName_Data", - table: "PersistedScheduledCommand", + name: "IX_ScheduledCommand_CommandName_Data", + table: "ScheduledCommand", columns: new[] { "CommandName", "Data" }, unique: true); migrationBuilder.CreateIndex( - name: "IX_PersistedScheduledCommand_ExecuteTime", - table: "PersistedScheduledCommand", + name: "IX_ScheduledCommand_ExecuteTime", + table: "ScheduledCommand", column: "ExecuteTime"); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( - name: "PersistedScheduledCommand"); + name: "ScheduledCommand"); migrationBuilder.AlterColumn( name: "InstanceId", diff --git a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs index cd2b9ceeb..8a3e02e9b 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs @@ -207,7 +207,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("CommandName", "Data") .IsUnique(); - b.ToTable("PersistedScheduledCommand"); + b.ToTable("ScheduledCommand"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211015204734_scheduled-commands.Designer.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211023161649_scheduled-commands.Designer.cs similarity index 99% rename from src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211015204734_scheduled-commands.Designer.cs rename to src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211023161649_scheduled-commands.Designer.cs index caa2f0941..0608d5e41 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211015204734_scheduled-commands.Designer.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211023161649_scheduled-commands.Designer.cs @@ -10,7 +10,7 @@ namespace WorkflowCore.Persistence.PostgreSQL.Migrations { [DbContext(typeof(PostgresContext))] - [Migration("20211015204734_scheduled-commands")] + [Migration("20211023161649_scheduled-commands")] partial class scheduledcommands { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -216,7 +216,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("CommandName", "Data") .IsUnique(); - b.ToTable("PersistedScheduledCommand"); + b.ToTable("ScheduledCommand", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211015204734_scheduled-commands.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211023161649_scheduled-commands.cs similarity index 73% rename from src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211015204734_scheduled-commands.cs rename to src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211023161649_scheduled-commands.cs index 23eff0eb2..0f1302181 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211015204734_scheduled-commands.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20211023161649_scheduled-commands.cs @@ -8,7 +8,8 @@ public partial class scheduledcommands : Migration protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( - name: "PersistedScheduledCommand", + name: "ScheduledCommand", + schema: "wfc", columns: table => new { PersistenceId = table.Column(type: "bigint", nullable: false) @@ -19,25 +20,28 @@ protected override void Up(MigrationBuilder migrationBuilder) }, constraints: table => { - table.PrimaryKey("PK_PersistedScheduledCommand", x => x.PersistenceId); + table.PrimaryKey("PK_ScheduledCommand", x => x.PersistenceId); }); migrationBuilder.CreateIndex( - name: "IX_PersistedScheduledCommand_CommandName_Data", - table: "PersistedScheduledCommand", + name: "IX_ScheduledCommand_CommandName_Data", + schema: "wfc", + table: "ScheduledCommand", columns: new[] { "CommandName", "Data" }, unique: true); migrationBuilder.CreateIndex( - name: "IX_PersistedScheduledCommand_ExecuteTime", - table: "PersistedScheduledCommand", + name: "IX_ScheduledCommand_ExecuteTime", + schema: "wfc", + table: "ScheduledCommand", column: "ExecuteTime"); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( - name: "PersistedScheduledCommand"); + name: "ScheduledCommand", + schema: "wfc"); } } } diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs index 76c681d8d..d0278e0c8 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs @@ -214,7 +214,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("CommandName", "Data") .IsUnique(); - b.ToTable("PersistedScheduledCommand"); + b.ToTable("ScheduledCommand", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211015215114_scheduled-commands.Designer.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211023161544_scheduled-commands.Designer.cs similarity index 98% rename from src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211015215114_scheduled-commands.Designer.cs rename to src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211023161544_scheduled-commands.Designer.cs index 489276722..84bed0be0 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211015215114_scheduled-commands.Designer.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211023161544_scheduled-commands.Designer.cs @@ -10,7 +10,7 @@ namespace WorkflowCore.Persistence.SqlServer.Migrations { [DbContext(typeof(SqlServerContext))] - [Migration("20211015215114_scheduled-commands")] + [Migration("20211023161544_scheduled-commands")] partial class scheduledcommands { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -204,6 +204,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("PersistenceId") .ValueGeneratedOnAdd() .HasColumnType("bigint") + .HasAnnotation("SqlServer:IdentityIncrement", 1) + .HasAnnotation("SqlServer:IdentitySeed", 1) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("CommandName") @@ -225,7 +227,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .IsUnique() .HasFilter("[CommandName] IS NOT NULL AND [Data] IS NOT NULL"); - b.ToTable("PersistedScheduledCommand"); + b.ToTable("ScheduledCommand", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211015215114_scheduled-commands.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211023161544_scheduled-commands.cs similarity index 72% rename from src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211015215114_scheduled-commands.cs rename to src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211023161544_scheduled-commands.cs index 357fbe2f1..2d5ec1572 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211015215114_scheduled-commands.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/20211023161544_scheduled-commands.cs @@ -7,7 +7,8 @@ public partial class scheduledcommands : Migration protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( - name: "PersistedScheduledCommand", + name: "ScheduledCommand", + schema: "wfc", columns: table => new { PersistenceId = table.Column(type: "bigint", nullable: false) @@ -18,26 +19,29 @@ protected override void Up(MigrationBuilder migrationBuilder) }, constraints: table => { - table.PrimaryKey("PK_PersistedScheduledCommand", x => x.PersistenceId); + table.PrimaryKey("PK_ScheduledCommand", x => x.PersistenceId); }); migrationBuilder.CreateIndex( - name: "IX_PersistedScheduledCommand_CommandName_Data", - table: "PersistedScheduledCommand", + name: "IX_ScheduledCommand_CommandName_Data", + schema: "wfc", + table: "ScheduledCommand", columns: new[] { "CommandName", "Data" }, unique: true, filter: "[CommandName] IS NOT NULL AND [Data] IS NOT NULL"); migrationBuilder.CreateIndex( - name: "IX_PersistedScheduledCommand_ExecuteTime", - table: "PersistedScheduledCommand", + name: "IX_ScheduledCommand_ExecuteTime", + schema: "wfc", + table: "ScheduledCommand", column: "ExecuteTime"); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( - name: "PersistedScheduledCommand"); + name: "ScheduledCommand", + schema: "wfc"); } } } diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs index df593d220..39da38276 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs @@ -202,6 +202,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PersistenceId") .ValueGeneratedOnAdd() .HasColumnType("bigint") + .HasAnnotation("SqlServer:IdentityIncrement", 1) + .HasAnnotation("SqlServer:IdentitySeed", 1) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("CommandName") @@ -223,7 +225,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsUnique() .HasFilter("[CommandName] IS NOT NULL AND [Data] IS NOT NULL"); - b.ToTable("PersistedScheduledCommand"); + b.ToTable("ScheduledCommand", "wfc"); }); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => From eb28727f2d0c55af0acefe78d12a25bd5b45e616 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sun, 31 Oct 2021 10:08:29 -0700 Subject: [PATCH 186/342] release notes --- ReleaseNotes/{3.7.0.md => 3.6.0.md} | 2 +- WorkflowCore.sln | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename ReleaseNotes/{3.7.0.md => 3.6.0.md} (95%) diff --git a/ReleaseNotes/3.7.0.md b/ReleaseNotes/3.6.0.md similarity index 95% rename from ReleaseNotes/3.7.0.md rename to ReleaseNotes/3.6.0.md index a6a8ec126..697976a46 100644 --- a/ReleaseNotes/3.7.0.md +++ b/ReleaseNotes/3.6.0.md @@ -1,4 +1,4 @@ -# Workflow Core 3.7.0 +# Workflow Core 3.6.0 ## Scheduled Commands diff --git a/WorkflowCore.sln b/WorkflowCore.sln index cf389574e..26bc01cf6 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -105,7 +105,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReleaseNotes", "ReleaseNote ReleaseNotes\3.1.0.md = ReleaseNotes\3.1.0.md ReleaseNotes\3.3.0.md = ReleaseNotes\3.3.0.md ReleaseNotes\3.4.0.md = ReleaseNotes\3.4.0.md - ReleaseNotes\3.7.0.md = ReleaseNotes\3.7.0.md + ReleaseNotes\3.6.0.md = ReleaseNotes\3.6.0.md EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample14", "src\samples\WorkflowCore.Sample14\WorkflowCore.Sample14.csproj", "{6BC66637-B42A-4334-ADFB-DBEC9F29D293}" From a03137b04e3f1ad670b660bb9a3f1e3da6fe43f7 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 10 Nov 2021 11:45:51 -0800 Subject: [PATCH 187/342] fix bug --- src/Directory.Build.props | 8 ++++---- .../Services/BackgroundTasks/RunnablePoller.cs | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 7c162693d..f95b297ab 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.6.0 - 3.6.0.0 - 3.6.0.0 + 3.6.1 + 3.6.1.0 + 3.6.1.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.6.0 + 3.6.1 diff --git a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs index b40a7a208..24b2af520 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs @@ -161,6 +161,9 @@ private async Task PollCommands() { try { + if (!_persistenceStore.SupportsScheduledCommands) + return; + if (await _lockProvider.AcquireLock("poll-commands", new CancellationToken())) { try From 8191dbae84713dd53c21a254afd182ace794975b Mon Sep 17 00:00:00 2001 From: Sergii Kram Date: Fri, 26 Nov 2021 15:52:12 +0200 Subject: [PATCH 188/342] Fix GitHub actions build. --- .github/workflows/dotnet.yml | 14 +++++++------- src/WorkflowCore/WorkflowCore.csproj | 4 +++- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 12b398572..8ede77162 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -16,20 +16,20 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: 5.0.* + dotnet-version: 3.1.* - name: Restore dependencies run: dotnet restore - name: Build run: dotnet build --no-restore - name: Unit Tests - run: dotnet test test/WorkflowCore.UnitTests --no-build --verbosity normal + run: dotnet test test/WorkflowCore.UnitTests --no-build --verbosity normal -p:ParallelizeTestCollections=false - name: Integration Tests - run: dotnet test test/WorkflowCore.IntegrationTests --no-build --verbosity normal + run: dotnet test test/WorkflowCore.IntegrationTests --no-build --verbosity normal -p:ParallelizeTestCollections=false - name: PostgreSQL Tests - run: dotnet test test/WorkflowCore.Tests.PostgreSQL --no-build --verbosity normal + run: dotnet test test/WorkflowCore.Tests.PostgreSQL --no-build --verbosity normal -p:ParallelizeTestCollections=false - name: Redis Tests - run: dotnet test test/WorkflowCore.Tests.Redis --no-build --verbosity normal + run: dotnet test test/WorkflowCore.Tests.Redis --no-build --verbosity normal -p:ParallelizeTestCollections=false - name: SQL Server Tests - run: dotnet test test/WorkflowCore.Tests.SqlServer --no-build --verbosity normal + run: dotnet test test/WorkflowCore.Tests.SqlServer --no-build --verbosity normal -p:ParallelizeTestCollections=false - name: Elasticsearch Tests - run: dotnet test test/WorkflowCore.Tests.Elasticsearch --no-build --verbosity normal + run: dotnet test test/WorkflowCore.Tests.Elasticsearch --no-build --verbosity normal -p:ParallelizeTestCollections=false diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 800ef9c08..7092270cf 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -26,7 +26,9 @@ - + + <_Parameter1>WorkflowCore.IntegrationTests + From 3066e05280e390858eb579cbd2c30c61f1e14929 Mon Sep 17 00:00:00 2001 From: potatopeelings Date: Sat, 18 Dec 2021 20:46:35 +1100 Subject: [PATCH 189/342] Resolve #957, E11000 duplicate key error --- .../Services/MongoPersistenceProvider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index ac65eb39b..e0147f5a4 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -315,9 +315,9 @@ public async Task ScheduleCommand(ScheduledCommand command) { await ScheduledCommands.InsertOneAsync(command); } - catch (MongoBulkWriteException ex) + catch (MongoWriteException ex) { - if (ex.WriteErrors.All(x => x.Category == ServerErrorCategory.DuplicateKey)) + if (ex.WriteError?.Category == ServerErrorCategory.DuplicateKey) return; throw; } From 23f5f274ca44800ab86e1cd9af916ded73e5733c Mon Sep 17 00:00:00 2001 From: potatopeelings Date: Mon, 20 Dec 2021 09:06:46 +1100 Subject: [PATCH 190/342] Resolve #957, Add back MongoBulkWriteException --- .../Services/MongoPersistenceProvider.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index e0147f5a4..06be13355 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -321,6 +321,12 @@ public async Task ScheduleCommand(ScheduledCommand command) return; throw; } + catch (MongoBulkWriteException ex) + { + if (ex.WriteErrors.All(x => x.Category == ServerErrorCategory.DuplicateKey)) + return; + throw; + } } public async Task ProcessCommands(DateTimeOffset asOf, Func action, CancellationToken cancellationToken = default) From 40787a148ec0d52c7cce49c1efa9eb5560361447 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Mon, 20 Dec 2021 11:04:00 -0800 Subject: [PATCH 191/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index f95b297ab..29d5fdae3 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.6.1 - 3.6.1.0 - 3.6.1.0 + 3.6.2 + 3.6.2.0 + 3.6.2.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.6.1 + 3.6.2 From f86a5166e8658669ffefe4c86a605489e886aa6a Mon Sep 17 00:00:00 2001 From: Denis Zhevagin Date: Fri, 7 Jan 2022 17:36:43 -0800 Subject: [PATCH 192/342] Removed hard coded Max Concurrent Items in Event Consumer. That significantly impact performance in a lot of events scenario. --- src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs index 9635df3ad..7f47d8ef8 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs @@ -17,7 +17,7 @@ internal class EventConsumer : QueueConsumer, IBackgroundTask private readonly IDistributedLockProvider _lockProvider; private readonly IDateTimeProvider _datetimeProvider; private readonly IGreyList _greylist; - protected override int MaxConcurrentItems => 2; + protected override QueueType Queue => QueueType.Event; public EventConsumer(IWorkflowRepository workflowRepository, ISubscriptionRepository subscriptionRepository, IEventRepository eventRepository, IQueueProvider queueProvider, ILoggerFactory loggerFactory, IServiceProvider serviceProvider, IWorkflowRegistry registry, IDistributedLockProvider lockProvider, WorkflowOptions options, IDateTimeProvider datetimeProvider, IGreyList greylist) From 17610b3cd5a7097ea3e33aa60cf53ab6332a9d8e Mon Sep 17 00:00:00 2001 From: Gabriel Lucaci Date: Fri, 18 Feb 2022 16:40:36 +0100 Subject: [PATCH 193/342] Add ActivitySource/OpenTelemetry support --- src/WorkflowCore/Models/WorkflowOptions.cs | 5 + .../Services/BackgroundTasks/EventConsumer.cs | 2 + .../Services/BackgroundTasks/IndexConsumer.cs | 2 + .../Services/BackgroundTasks/QueueConsumer.cs | 20 ++- .../BackgroundTasks/RunnablePoller.cs | 24 +++- .../BackgroundTasks/WorkflowConsumer.cs | 4 + src/WorkflowCore/Services/WorkflowActivity.cs | 124 ++++++++++++++++++ src/WorkflowCore/Services/WorkflowExecutor.cs | 1 + src/WorkflowCore/Services/WorkflowHost.cs | 44 ++++--- src/WorkflowCore/WorkflowCore.csproj | 1 + 10 files changed, 208 insertions(+), 19 deletions(-) create mode 100644 src/WorkflowCore/Services/WorkflowActivity.cs diff --git a/src/WorkflowCore/Models/WorkflowOptions.cs b/src/WorkflowCore/Models/WorkflowOptions.cs index fb1ae9a7e..8913c32c2 100644 --- a/src/WorkflowCore/Models/WorkflowOptions.cs +++ b/src/WorkflowCore/Models/WorkflowOptions.cs @@ -75,6 +75,11 @@ public void UseErrorRetryInterval(TimeSpan interval) ErrorRetryInterval = interval; } + public void UseIdleTime(TimeSpan interval) + { + IdleTime = interval; + } + public void UseMaxConcurrentWorkflows(int maxConcurrentWorkflows) { MaxConcurrentWorkflows = maxConcurrentWorkflows; diff --git a/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs index 9635df3ad..dd7323b01 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs @@ -43,6 +43,8 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance { cancellationToken.ThrowIfCancellationRequested(); var evt = await _eventRepository.GetEvent(itemId, cancellationToken); + + WorkflowActivity.Enrich(evt); if (evt.IsProcessed) { _greylist.Add($"evt:{evt.Id}"); diff --git a/src/WorkflowCore/Services/BackgroundTasks/IndexConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/IndexConsumer.cs index 10899af10..29565e647 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/IndexConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/IndexConsumer.cs @@ -32,6 +32,8 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance try { var workflow = await FetchWorkflow(itemId); + + WorkflowActivity.Enrich(workflow, "index"); await _searchIndex.IndexWorkflow(workflow); lock (_errorCounts) { diff --git a/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs index b1bb7c5b9..1476e8b96 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using ConcurrentCollections; using Microsoft.Extensions.Logging; +using OpenTelemetry.Trace; using WorkflowCore.Interface; using WorkflowCore.Models; @@ -61,6 +63,7 @@ private async Task Execute() while (!cancelToken.IsCancellationRequested) { + Activity activity = default; try { var activeCount = 0; @@ -74,15 +77,19 @@ private async Task Execute() continue; } + activity = WorkflowActivity.StartConsume(Queue); var item = await QueueProvider.DequeueWork(Queue, cancelToken); if (item == null) { + activity?.Dispose(); if (!QueueProvider.IsDequeueBlocking) await Task.Delay(Options.IdleTime, cancelToken); continue; } + activity?.EnrichWithDequeuedItem(item); + var hasTask = false; lock (_activeTasks) { @@ -93,8 +100,9 @@ private async Task Execute() _secondPasses.Add(item); if (!EnableSecondPasses) await QueueProvider.QueueWork(item, Queue); + activity?.Dispose(); continue; - } + } _secondPasses.TryRemove(item); @@ -103,7 +111,7 @@ private async Task Execute() { _activeTasks.Add(item, waitHandle); } - var task = ExecuteItem(item, waitHandle); + var task = ExecuteItem(item, waitHandle, activity); } catch (OperationCanceledException) { @@ -111,6 +119,11 @@ private async Task Execute() catch (Exception ex) { Logger.LogError(ex, ex.Message); + activity?.RecordException(ex); + } + finally + { + activity?.Dispose(); } } @@ -124,7 +137,7 @@ private async Task Execute() handle.WaitOne(); } - private async Task ExecuteItem(string itemId, EventWaitHandle waitHandle) + private async Task ExecuteItem(string itemId, EventWaitHandle waitHandle, Activity activity) { try { @@ -142,6 +155,7 @@ private async Task ExecuteItem(string itemId, EventWaitHandle waitHandle) catch (Exception ex) { Logger.LogError(default(EventId), ex, $"Error executing item {itemId} - {ex.Message}"); + activity?.RecordException(ex); } finally { diff --git a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs index d7ec5e595..fcd2abd92 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs @@ -1,8 +1,10 @@ using System; +using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using OpenTelemetry.Trace; using WorkflowCore.Interface; using WorkflowCore.Models; @@ -57,13 +59,14 @@ private async void PollRunnables(object target) private async Task PollWorkflows() { + var activity = WorkflowActivity.StartPoll("workflows"); try { if (await _lockProvider.AcquireLock("poll runnables", new CancellationToken())) { try { - _logger.LogDebug("Polling for runnable workflows"); + _logger.LogDebug("Polling for runnable workflows"); var runnables = await _persistenceStore.GetRunnableInstances(_dateTimeProvider.Now); foreach (var item in runnables) @@ -83,6 +86,7 @@ await _persistenceStore.ScheduleCommand(new ScheduledCommand() catch (Exception ex) { _logger.LogError(ex, ex.Message); + activity?.RecordException(ex); } } if (_greylist.Contains($"wf:{item}")) @@ -104,11 +108,17 @@ await _persistenceStore.ScheduleCommand(new ScheduledCommand() catch (Exception ex) { _logger.LogError(ex, ex.Message); + activity?.RecordException(ex); + } + finally + { + activity?.Dispose(); } } private async Task PollEvents() { + var activity = WorkflowActivity.StartPoll("events"); try { if (await _lockProvider.AcquireLock("unprocessed events", new CancellationToken())) @@ -135,6 +145,7 @@ await _persistenceStore.ScheduleCommand(new ScheduledCommand() catch (Exception ex) { _logger.LogError(ex, ex.Message); + activity?.RecordException(ex); } } if (_greylist.Contains($"evt:{item}")) @@ -156,11 +167,17 @@ await _persistenceStore.ScheduleCommand(new ScheduledCommand() catch (Exception ex) { _logger.LogError(ex, ex.Message); + activity?.RecordException(ex); + } + finally + { + activity?.Dispose(); } } private async Task PollCommands() { + var activity = WorkflowActivity.StartPoll("commands"); try { if (!_persistenceStore.SupportsScheduledCommands) @@ -193,6 +210,11 @@ await _persistenceStore.ProcessCommands(new DateTimeOffset(_dateTimeProvider.Utc catch (Exception ex) { _logger.LogError(ex, ex.Message); + activity?.RecordException(ex); + } + finally + { + activity?.Dispose(); } } } diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index a387848b6..b3dd4aa0b 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -43,6 +44,8 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance { cancellationToken.ThrowIfCancellationRequested(); workflow = await _persistenceStore.GetWorkflowInstance(itemId, cancellationToken); + + WorkflowActivity.Enrich(workflow, "process"); if (workflow.Status == WorkflowStatus.Runnable) { try @@ -51,6 +54,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance } finally { + WorkflowActivity.Enrich(result); await _persistenceStore.PersistWorkflow(workflow, cancellationToken); await QueueProvider.QueueWork(itemId, QueueType.Index); _greylist.Remove($"wf:{itemId}"); diff --git a/src/WorkflowCore/Services/WorkflowActivity.cs b/src/WorkflowCore/Services/WorkflowActivity.cs new file mode 100644 index 000000000..b580f98b6 --- /dev/null +++ b/src/WorkflowCore/Services/WorkflowActivity.cs @@ -0,0 +1,124 @@ +using System.Diagnostics; +using OpenTelemetry.Trace; +using WorkflowCore.Interface; +using WorkflowCore.Models; + +namespace WorkflowCore.Services +{ + internal static class WorkflowActivity + { + private static readonly ActivitySource ActivitySource = new ActivitySource("WorkflowCore"); + + internal static Activity StartHost() + { + var activityName = "workflow start host"; + return ActivitySource.StartRootActivity(activityName, ActivityKind.Internal); + } + + internal static Activity StartConsume(QueueType queueType) + { + var activityName = $"workflow consume {GetQueueType(queueType)}"; + var activity = ActivitySource.StartRootActivity(activityName, ActivityKind.Consumer); + + activity?.SetTag("workflow.queue", queueType); + + return activity; + } + + + internal static Activity StartPoll(string type) + { + var activityName = $"workflow poll {type}"; + var activity = ActivitySource.StartRootActivity(activityName, ActivityKind.Client); + + activity?.SetTag("workflow.poll", type); + + return activity; + } + + internal static void Enrich(WorkflowInstance workflow, string action) + { + var activity = Activity.Current; + if (activity != null) + { + activity.DisplayName = $"workflow {action} {workflow.WorkflowDefinitionId}"; + activity.SetTag("workflow.id", workflow.Id); + activity.SetTag("workflow.definition", workflow.WorkflowDefinitionId); + activity.SetTag("workflow.status", workflow.Status); + } + } + + internal static void Enrich(WorkflowStep workflowStep) + { + var activity = Activity.Current; + if (activity != null) + { + var stepName = string.IsNullOrEmpty(workflowStep.Name) + ? "inline" + : workflowStep.Name; + + activity.DisplayName += $" step {stepName}"; + activity.SetTag("workflow.step.id", workflowStep.Id); + activity.SetTag("workflow.step.name", workflowStep.Name); + activity.SetTag("workflow.step.type", workflowStep.BodyType.Name); + } + } + + internal static void Enrich(WorkflowExecutorResult result) + { + var activity = Activity.Current; + if (activity != null) + { + activity.SetTag("workflow.subscriptions.count", result.Subscriptions.Count); + activity.SetTag("workflow.errors.count", result.Errors.Count); + + if (result.Errors.Count > 0) + { + activity.SetStatus(Status.Error); + activity.SetStatus(ActivityStatusCode.Error); + } + } + } + + internal static void Enrich(Event evt) + { + var activity = Activity.Current; + if (activity != null) + { + activity.DisplayName = $"workflow process {evt.EventName}"; + activity.SetTag("workflow.event.id", evt.Id); + activity.SetTag("workflow.event.name", evt.EventName); + activity.SetTag("workflow.event.processed", evt.IsProcessed); + } + } + + internal static void EnrichWithDequeuedItem(this Activity activity, string item) + { + if (activity != null) + { + activity.SetTag("workflow.queue.item", item); + } + } + + private static Activity StartRootActivity( + this ActivitySource activitySource, + string name, + ActivityKind kind) + { + Activity.Current = null; + + return activitySource.StartActivity(name, kind); + } + + private static string GetQueueType(QueueType queueType) + { + switch (queueType) + { + case QueueType.Workflow: return "workflow"; + case QueueType.Event: return "event"; + case QueueType.Index: return "index"; + default: return "unknown"; + } + } + } +} \ No newline at end of file diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index ebdc818fe..145f02d41 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -73,6 +73,7 @@ public async Task Execute(WorkflowInstance workflow, Can continue; } + WorkflowActivity.Enrich(step); try { if (!InitializeStep(workflow, step, wfResult, def, pointer)) diff --git a/src/WorkflowCore/Services/WorkflowHost.cs b/src/WorkflowCore/Services/WorkflowHost.cs index ca5e04b2f..73c8850fa 100644 --- a/src/WorkflowCore/Services/WorkflowHost.cs +++ b/src/WorkflowCore/Services/WorkflowHost.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using OpenTelemetry.Trace; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Models.LifeCycleEvents; @@ -83,21 +84,34 @@ public void Start() public async Task StartAsync(CancellationToken cancellationToken) { - _shutdown = false; - PersistenceStore.EnsureStoreExists(); - await QueueProvider.Start(); - await LockProvider.Start(); - await _lifeCycleEventHub.Start(); - await _searchIndex.Start(); - - // Event subscriptions are removed when stopping the event hub. - // Add them when starting. - AddEventSubscriptions(); - - Logger.LogInformation("Starting background tasks"); - - foreach (var task in _backgroundTasks) - task.Start(); + var activity = WorkflowActivity.StartHost(); + try + { + _shutdown = false; + PersistenceStore.EnsureStoreExists(); + await QueueProvider.Start(); + await LockProvider.Start(); + await _lifeCycleEventHub.Start(); + await _searchIndex.Start(); + + // Event subscriptions are removed when stopping the event hub. + // Add them when starting. + AddEventSubscriptions(); + + Logger.LogInformation("Starting background tasks"); + + foreach (var task in _backgroundTasks) + task.Start(); + } + catch (Exception ex) + { + activity.RecordException(ex); + throw; + } + finally + { + activity?.Dispose(); + } } public void Stop() diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 7092270cf..4eb4ff1e5 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -26,6 +26,7 @@ + <_Parameter1>WorkflowCore.IntegrationTests From 42b3738739094702855e030db218124017857136 Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 15 Mar 2022 16:46:52 +0100 Subject: [PATCH 194/342] Downgrade OpenTelemetry.Api package to last stable version --- src/WorkflowCore/WorkflowCore.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 4eb4ff1e5..7177f0adf 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -26,7 +26,7 @@ - + <_Parameter1>WorkflowCore.IntegrationTests From 0867f48ba3b509186588926493074fd0988979c1 Mon Sep 17 00:00:00 2001 From: Luis Fernando Bertucci Date: Tue, 15 Mar 2022 16:39:34 -0300 Subject: [PATCH 195/342] Update dependencies from 'WorkflowCore.Providers.AWS': AWSSDK.DynamoDBv2 to 3.7.3.11, AWSSDK.Kinesis to 3.7.1.32 and AWSSDK.SQS to 3.7.2.33 --- .../WorkflowCore.Providers.AWS.csproj | 6 +++--- .../WorkflowCore.Sample04/WorkflowCore.Sample04.csproj | 2 +- .../WorkflowCore.Tests.DynamoDB.csproj | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj index 49b7c2916..5600452a2 100644 --- a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj +++ b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj @@ -14,9 +14,9 @@ - - - + + + diff --git a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj index ddae958be..fd78be8ac 100644 --- a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj +++ b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj @@ -24,7 +24,7 @@ - + diff --git a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj index f275a05cf..126ac0099 100644 --- a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj +++ b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj @@ -7,7 +7,7 @@ - + From dadac9aae992968c55949d34cfde15bfce154143 Mon Sep 17 00:00:00 2001 From: glucaci Date: Mon, 28 Mar 2022 09:38:10 +0200 Subject: [PATCH 196/342] Fix build --- src/WorkflowCore/WorkflowCore.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 7177f0adf..0a238b8aa 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -27,6 +27,7 @@ + <_Parameter1>WorkflowCore.IntegrationTests From 98c54362b2ecd0700c9bd01eef14c3fcffaaecad Mon Sep 17 00:00:00 2001 From: glucaci Date: Mon, 28 Mar 2022 10:37:21 +0200 Subject: [PATCH 197/342] Cleanup samples and tests --- WorkflowCore.sln | 2 +- {test => src}/WorkflowCore.Testing/JsonWorkflowTest.cs | 0 .../WorkflowCore.Testing/WorkflowCore.Testing.csproj | 0 {test => src}/WorkflowCore.Testing/WorkflowTest.cs | 0 {test => src}/WorkflowCore.Testing/YamlWorkflowTest.cs | 0 {test => src}/WorkflowCore.Testing/readme.md | 0 src/samples/Directory.Build.props | 7 +++++++ src/samples/WebApiSample/Directory.Build.props | 3 +++ src/samples/WebApiSample/WebApiSample/WebApiSample.csproj | 1 - .../WorkflowCore.Sample01/WorkflowCore.Sample01.csproj | 1 - .../WorkflowCore.Sample02/WorkflowCore.Sample02.csproj | 1 - .../WorkflowCore.Sample03/WorkflowCore.Sample03.csproj | 1 - .../WorkflowCore.Sample04/WorkflowCore.Sample04.csproj | 1 - .../WorkflowCore.Sample05/WorkflowCore.Sample05.csproj | 1 - .../WorkflowCore.Sample06/WorkflowCore.Sample06.csproj | 1 - .../WorkflowCore.Sample07/WorkflowCore.Sample07.csproj | 1 - .../WorkflowCore.Sample08/WorkflowCore.Sample08.csproj | 1 - .../WorkflowCore.Sample09/WorkflowCore.Sample09.csproj | 1 - .../WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj | 1 - .../WorkflowCore.Sample10/WorkflowCore.Sample10.csproj | 1 - .../WorkflowCore.Sample11/WorkflowCore.Sample11.csproj | 1 - .../WorkflowCore.Sample12/WorkflowCore.Sample12.csproj | 1 - .../WorkflowCore.Sample13/WorkflowCore.Sample13.csproj | 1 - .../WorkflowCore.Sample14/WorkflowCore.Sample14.csproj | 1 - .../WorkflowCore.Sample15/WorkflowCore.Sample15.csproj | 1 - .../WorkflowCore.Sample16/WorkflowCore.Sample16.csproj | 1 - .../WorkflowCore.Sample17/WorkflowCore.Sample17.csproj | 1 - .../WorkflowCore.Sample18/WorkflowCore.Sample18.csproj | 1 - .../WorkflowCore.Sample19/WorkflowCore.Sample19.csproj | 1 - .../WorkflowCore.TestSample01.csproj | 6 +----- test/Directory.Build.props | 7 +++++++ test/Docker.Testify/Docker.Testify.csproj | 4 ---- test/ScratchPad/ScratchPad.csproj | 1 - .../WorkflowCore.IntegrationTests.csproj | 3 +-- .../WorkflowCore.TestAssets.csproj | 1 - .../WorkflowCore.Tests.DynamoDB.csproj | 6 ------ .../WorkflowCore.Tests.Elasticsearch.csproj | 6 ------ .../WorkflowCore.Tests.MongoDB.csproj | 3 +-- .../WorkflowCore.Tests.MySQL.csproj | 8 +------- .../WorkflowCore.Tests.PostgreSQL.csproj | 3 +-- .../WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj | 6 ------ .../WorkflowCore.Tests.Redis.csproj | 6 ------ .../WorkflowCore.Tests.SqlServer.csproj | 4 ---- .../WorkflowCore.Tests.Sqlite.csproj | 4 ---- test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj | 1 - 45 files changed, 23 insertions(+), 79 deletions(-) rename {test => src}/WorkflowCore.Testing/JsonWorkflowTest.cs (100%) rename {test => src}/WorkflowCore.Testing/WorkflowCore.Testing.csproj (100%) rename {test => src}/WorkflowCore.Testing/WorkflowTest.cs (100%) rename {test => src}/WorkflowCore.Testing/YamlWorkflowTest.cs (100%) rename {test => src}/WorkflowCore.Testing/readme.md (100%) create mode 100644 src/samples/Directory.Build.props create mode 100644 src/samples/WebApiSample/Directory.Build.props create mode 100644 test/Directory.Build.props diff --git a/WorkflowCore.sln b/WorkflowCore.sln index 26bc01cf6..e7fb81a2e 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.sln @@ -110,7 +110,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReleaseNotes", "ReleaseNote EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample14", "src\samples\WorkflowCore.Sample14\WorkflowCore.Sample14.csproj", "{6BC66637-B42A-4334-ADFB-DBEC9F29D293}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Testing", "test\WorkflowCore.Testing\WorkflowCore.Testing.csproj", "{62A9709E-27DA-42EE-B94F-5AF431D86354}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Testing", "src\WorkflowCore.Testing\WorkflowCore.Testing.csproj", "{62A9709E-27DA-42EE-B94F-5AF431D86354}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.TestSample01", "src\samples\WorkflowCore.TestSample01\WorkflowCore.TestSample01.csproj", "{0E3C1496-8E7C-411A-A536-C7C9CE4EED4E}" EndProject diff --git a/test/WorkflowCore.Testing/JsonWorkflowTest.cs b/src/WorkflowCore.Testing/JsonWorkflowTest.cs similarity index 100% rename from test/WorkflowCore.Testing/JsonWorkflowTest.cs rename to src/WorkflowCore.Testing/JsonWorkflowTest.cs diff --git a/test/WorkflowCore.Testing/WorkflowCore.Testing.csproj b/src/WorkflowCore.Testing/WorkflowCore.Testing.csproj similarity index 100% rename from test/WorkflowCore.Testing/WorkflowCore.Testing.csproj rename to src/WorkflowCore.Testing/WorkflowCore.Testing.csproj diff --git a/test/WorkflowCore.Testing/WorkflowTest.cs b/src/WorkflowCore.Testing/WorkflowTest.cs similarity index 100% rename from test/WorkflowCore.Testing/WorkflowTest.cs rename to src/WorkflowCore.Testing/WorkflowTest.cs diff --git a/test/WorkflowCore.Testing/YamlWorkflowTest.cs b/src/WorkflowCore.Testing/YamlWorkflowTest.cs similarity index 100% rename from test/WorkflowCore.Testing/YamlWorkflowTest.cs rename to src/WorkflowCore.Testing/YamlWorkflowTest.cs diff --git a/test/WorkflowCore.Testing/readme.md b/src/WorkflowCore.Testing/readme.md similarity index 100% rename from test/WorkflowCore.Testing/readme.md rename to src/WorkflowCore.Testing/readme.md diff --git a/src/samples/Directory.Build.props b/src/samples/Directory.Build.props new file mode 100644 index 000000000..0f8bd594d --- /dev/null +++ b/src/samples/Directory.Build.props @@ -0,0 +1,7 @@ + + + net6.0;netcoreapp3.1 + latest + false + + \ No newline at end of file diff --git a/src/samples/WebApiSample/Directory.Build.props b/src/samples/WebApiSample/Directory.Build.props new file mode 100644 index 000000000..b312f7757 --- /dev/null +++ b/src/samples/WebApiSample/Directory.Build.props @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/samples/WebApiSample/WebApiSample/WebApiSample.csproj b/src/samples/WebApiSample/WebApiSample/WebApiSample.csproj index e5545be0c..3290c0dbf 100644 --- a/src/samples/WebApiSample/WebApiSample/WebApiSample.csproj +++ b/src/samples/WebApiSample/WebApiSample/WebApiSample.csproj @@ -1,7 +1,6 @@  - netcoreapp2.1 Linux ..\docker-compose.dcproj diff --git a/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj b/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj index e4a09e491..d20a6bc51 100644 --- a/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj +++ b/src/samples/WorkflowCore.Sample01/WorkflowCore.Sample01.csproj @@ -1,7 +1,6 @@  - netcoreapp2.2 WorkflowCore.Sample01 Exe WorkflowCore.Sample01 diff --git a/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj b/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj index 0765d50c3..be4e85c2d 100644 --- a/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj +++ b/src/samples/WorkflowCore.Sample02/WorkflowCore.Sample02.csproj @@ -1,7 +1,6 @@  - netcoreapp2.2 WorkflowCore.Sample02 Exe WorkflowCore.Sample02 diff --git a/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj b/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj index d211d3d2f..72c15f156 100644 --- a/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj +++ b/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj @@ -1,7 +1,6 @@  - netcoreapp3.1 WorkflowCore.Sample03 Exe WorkflowCore.Sample03 diff --git a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj index ddae958be..36bc3c4d3 100644 --- a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj +++ b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj @@ -1,7 +1,6 @@  - netcoreapp3.1 WorkflowCore.Sample04 Exe WorkflowCore.Sample04 diff --git a/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj b/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj index 592fa228b..bbfd7f7c7 100644 --- a/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj +++ b/src/samples/WorkflowCore.Sample05/WorkflowCore.Sample05.csproj @@ -1,7 +1,6 @@  - netcoreapp2.0 WorkflowCore.Sample05 Exe WorkflowCore.Sample05 diff --git a/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj b/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj index b61478b9e..47e03b0ee 100644 --- a/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj +++ b/src/samples/WorkflowCore.Sample06/WorkflowCore.Sample06.csproj @@ -1,7 +1,6 @@  - netcoreapp2.0 WorkflowCore.Sample06 Exe WorkflowCore.Sample06 diff --git a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj index 2f5937f36..89096e798 100644 --- a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj +++ b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj @@ -1,7 +1,6 @@  - netcoreapp3.1 true WorkflowCore.Sample07 Exe diff --git a/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj b/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj index 3ff429e28..f6ae3bcba 100644 --- a/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj +++ b/src/samples/WorkflowCore.Sample08/WorkflowCore.Sample08.csproj @@ -1,7 +1,6 @@  - netcoreapp3.0 WorkflowCore.Sample08 Exe WorkflowCore.Sample08 diff --git a/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj b/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj index 6f75a0d7d..e7c7206ec 100644 --- a/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj +++ b/src/samples/WorkflowCore.Sample09/WorkflowCore.Sample09.csproj @@ -2,7 +2,6 @@ Exe - netcoreapp3.0 diff --git a/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj b/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj index e569ec895..67c94bc64 100644 --- a/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj +++ b/src/samples/WorkflowCore.Sample09s/WorkflowCore.Sample09s.csproj @@ -2,7 +2,6 @@ Exe - netcoreapp3.0 diff --git a/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj b/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj index 6f75a0d7d..e7c7206ec 100644 --- a/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj +++ b/src/samples/WorkflowCore.Sample10/WorkflowCore.Sample10.csproj @@ -2,7 +2,6 @@ Exe - netcoreapp3.0 diff --git a/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj b/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj index b6454f6a2..106048445 100644 --- a/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj +++ b/src/samples/WorkflowCore.Sample11/WorkflowCore.Sample11.csproj @@ -2,7 +2,6 @@ Exe - netcoreapp2.2 diff --git a/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj b/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj index 9879baab2..e0fb0e8aa 100644 --- a/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj +++ b/src/samples/WorkflowCore.Sample12/WorkflowCore.Sample12.csproj @@ -2,7 +2,6 @@ Exe - netcoreapp3.0 diff --git a/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj b/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj index 34e1b0433..522eaac98 100644 --- a/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj +++ b/src/samples/WorkflowCore.Sample13/WorkflowCore.Sample13.csproj @@ -2,7 +2,6 @@ Exe - netcoreapp3.1 diff --git a/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj b/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj index 974472a25..539973bee 100644 --- a/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj +++ b/src/samples/WorkflowCore.Sample14/WorkflowCore.Sample14.csproj @@ -2,7 +2,6 @@ Exe - netcoreapp3.1 diff --git a/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj b/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj index c63fbd792..f8d1df555 100644 --- a/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj +++ b/src/samples/WorkflowCore.Sample15/WorkflowCore.Sample15.csproj @@ -2,7 +2,6 @@ Exe - netcoreapp2.2 diff --git a/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj b/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj index c63fbd792..f8d1df555 100644 --- a/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj +++ b/src/samples/WorkflowCore.Sample16/WorkflowCore.Sample16.csproj @@ -2,7 +2,6 @@ Exe - netcoreapp2.2 diff --git a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj index 766fc8e0c..aa4cb91d8 100644 --- a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj +++ b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj @@ -2,7 +2,6 @@ Exe - netcoreapp3.1 diff --git a/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj b/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj index 660b47511..c1c6e0846 100644 --- a/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj +++ b/src/samples/WorkflowCore.Sample18/WorkflowCore.Sample18.csproj @@ -2,7 +2,6 @@ Exe - netcoreapp3.0 diff --git a/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj b/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj index b2a7796c3..181b45e66 100644 --- a/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj +++ b/src/samples/WorkflowCore.Sample19/WorkflowCore.Sample19.csproj @@ -2,7 +2,6 @@ Exe - netcoreapp3.0 diff --git a/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj b/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj index 46df42954..308565745 100644 --- a/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj +++ b/src/samples/WorkflowCore.TestSample01/WorkflowCore.TestSample01.csproj @@ -1,9 +1,5 @@  - - netcoreapp3.1 - - @@ -15,7 +11,7 @@ - + diff --git a/test/Directory.Build.props b/test/Directory.Build.props new file mode 100644 index 000000000..0f8bd594d --- /dev/null +++ b/test/Directory.Build.props @@ -0,0 +1,7 @@ + + + net6.0;netcoreapp3.1 + latest + false + + \ No newline at end of file diff --git a/test/Docker.Testify/Docker.Testify.csproj b/test/Docker.Testify/Docker.Testify.csproj index 8d4989b7c..a83648df4 100644 --- a/test/Docker.Testify/Docker.Testify.csproj +++ b/test/Docker.Testify/Docker.Testify.csproj @@ -1,9 +1,5 @@  - - netstandard2.0 - - diff --git a/test/ScratchPad/ScratchPad.csproj b/test/ScratchPad/ScratchPad.csproj index 2b63861b1..fdd4f1a3d 100644 --- a/test/ScratchPad/ScratchPad.csproj +++ b/test/ScratchPad/ScratchPad.csproj @@ -1,7 +1,6 @@  - netcoreapp3.1 ScratchPad Exe ScratchPad diff --git a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj index f52ee0ba1..39390c2e6 100644 --- a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj +++ b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj @@ -1,7 +1,6 @@  - netcoreapp3.1 WorkflowCore.IntegrationTests WorkflowCore.IntegrationTests true @@ -14,7 +13,7 @@ - + diff --git a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj index 0ff0a1fc2..73bd5b39d 100644 --- a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj +++ b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj @@ -1,7 +1,6 @@  - netstandard2.0 WorkflowCore.TestAssets WorkflowCore.TestAssets false diff --git a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj index f275a05cf..b7d5a57b4 100644 --- a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj +++ b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj @@ -1,11 +1,5 @@ - - netcoreapp3.1 - - false - - diff --git a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj index 60e631bd7..887e2df63 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj +++ b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj @@ -1,11 +1,5 @@  - - netcoreapp3.1 - - false - - diff --git a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj index a76f2b513..98fdd4ce8 100644 --- a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj +++ b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj @@ -1,7 +1,6 @@  - netcoreapp3.1 WorkflowCore.Tests.MongoDB WorkflowCore.Tests.MongoDB true @@ -15,7 +14,7 @@ - + diff --git a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj index ff53c72b2..1432348e2 100644 --- a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj +++ b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj @@ -1,11 +1,5 @@ - - netcoreapp3.1 - - false - - @@ -18,7 +12,7 @@ - + diff --git a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj index 2fefbdea8..64b475b13 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj +++ b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj @@ -1,7 +1,6 @@  - netcoreapp3.1 WorkflowCore.Tests.PostgreSQL WorkflowCore.Tests.PostgreSQL true @@ -16,7 +15,7 @@ - + diff --git a/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj b/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj index 7ccd35c02..0173d76bd 100644 --- a/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj +++ b/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj @@ -1,11 +1,5 @@ - - netcoreapp3.1 - - false - - diff --git a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj index af4f4117d..0ee3705bf 100644 --- a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj +++ b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj @@ -1,11 +1,5 @@ - - netcoreapp3.1 - - false - - diff --git a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj index 497293aaf..36ee2a15d 100644 --- a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj +++ b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj @@ -1,9 +1,5 @@  - - netcoreapp3.1 - - diff --git a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj index 9598398f4..31f839cf3 100644 --- a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj +++ b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj @@ -1,9 +1,5 @@  - - netcoreapp3.1 - - diff --git a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj index 81ceeb3b1..f6ae01fbf 100644 --- a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj +++ b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj @@ -1,7 +1,6 @@  - netcoreapp3.1 WorkflowCore.UnitTests WorkflowCore.UnitTests true From 3c3b1ea47f655edb08bf7bbea3c9d35386506309 Mon Sep 17 00:00:00 2001 From: glucaci Date: Mon, 28 Mar 2022 10:43:24 +0200 Subject: [PATCH 198/342] Update build to .NET 6 --- .github/workflows/dotnet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 8ede77162..72d9e42ac 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -16,7 +16,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: 3.1.* + dotnet-version: 6.0.* - name: Restore dependencies run: dotnet restore - name: Build From a9e5012229d6ade7916bed9b6d142728ac1a5e84 Mon Sep 17 00:00:00 2001 From: glucaci Date: Mon, 28 Mar 2022 10:45:59 +0200 Subject: [PATCH 199/342] Add .netcoreapp 3.1 dependencie for tests --- .github/workflows/dotnet.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 72d9e42ac..9a49e0237 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -16,7 +16,9 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: 6.0.* + dotnet-version: | + 3.1.x + 6.0.x - name: Restore dependencies run: dotnet restore - name: Build From c166817fdcd580874794b34fc7f12cd6488cce2f Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 29 Mar 2022 17:51:02 +0200 Subject: [PATCH 200/342] Update packages for .NET6.0 --- ...orkflowCore.Persistence.EntityFramework.csproj | 11 +++++++++-- .../WorkflowCore.Persistence.MySQL.csproj | 10 +++++++++- .../WorkflowCore.Persistence.PostgreSQL.csproj | 15 +++++++++++++-- .../WorkflowCore.Persistence.SqlServer.csproj | 15 +++++++++++++-- .../WorkflowCore.Persistence.Sqlite.csproj | 8 ++++++-- .../WorkflowCore.Sample03.csproj | 1 - .../WorkflowCore.Sample04.csproj | 14 -------------- .../WorkflowCore.Sample07.csproj | 1 - .../WorkflowCore.Sample17.csproj | 4 ---- .../WorkflowCore.Tests.PostgreSQL.csproj | 1 - 10 files changed, 50 insertions(+), 30 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index 6e1206632..bb07fffd3 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -3,7 +3,7 @@ Workflow Core EntityFramework Core Persistence Provider Daniel Gerlag - netstandard2.1 + netstandard2.1;net6.0 WorkflowCore.Persistence.EntityFramework WorkflowCore.Persistence.EntityFramework workflow;.NET;Core;state machine;WorkflowCore;EntityFramework;EntityFrameworkCore @@ -21,9 +21,16 @@ - + + + + + + + + diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index 1b2fa9f6b..aaf1f79b0 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -4,7 +4,7 @@ Workflow Core MySQL Persistence Provider 1.0.0 Daniel Gerlag - netstandard2.1 + netstandard2.1;net6.0 WorkflowCore.Persistence.MySQL WorkflowCore.Persistence.MySQL workflow;.NET;Core;state machine;WorkflowCore;MySQL @@ -34,6 +34,14 @@ + + + all + runtime; build; native; contentfiles; analyzers + + + + diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index 3aa405620..5ff53cd02 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -3,7 +3,7 @@ Workflow Core PostgreSQL Persistence Provider Daniel Gerlag - netstandard2.1 + netstandard2.1;net6.0 WorkflowCore.Persistence.PostgreSQL WorkflowCore.Persistence.PostgreSQL workflow;.NET;Core;state machine;WorkflowCore;PostgreSQL @@ -22,7 +22,18 @@ - + + + + All + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index 38375e8e6..be099421a 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -4,7 +4,7 @@ Workflow Core SQL Server Persistence Provider 1.8.0 Daniel Gerlag - netstandard2.1 + netstandard2.1;net6.0 WorkflowCore.Persistence.SqlServer WorkflowCore.Persistence.SqlServer workflow;.NET;Core;state machine;WorkflowCore @@ -23,7 +23,18 @@ - + + + + All + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + All diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj index d4c73e037..0bd622bde 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj +++ b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj @@ -4,7 +4,7 @@ Workflow Core Sqlite Persistence Provider 1.5.0 Daniel Gerlag - netstandard2.1 + netstandard2.1;net6.0 WorkflowCore.Persistence.Sqlite WorkflowCore.Persistence.Sqlite workflow;.NET;Core;state machine;WorkflowCore;Sqlite @@ -23,7 +23,11 @@ - + + + + + diff --git a/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj b/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj index 72c15f156..180c03454 100644 --- a/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj +++ b/src/samples/WorkflowCore.Sample03/WorkflowCore.Sample03.csproj @@ -15,7 +15,6 @@ - diff --git a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj index 6e78c2961..5940a8e00 100644 --- a/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj +++ b/src/samples/WorkflowCore.Sample04/WorkflowCore.Sample04.csproj @@ -24,20 +24,6 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - diff --git a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj index 89096e798..1cc78f66f 100644 --- a/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj +++ b/src/samples/WorkflowCore.Sample07/WorkflowCore.Sample07.csproj @@ -25,7 +25,6 @@ - diff --git a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj index aa4cb91d8..f54a7ad6d 100644 --- a/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj +++ b/src/samples/WorkflowCore.Sample17/WorkflowCore.Sample17.csproj @@ -4,10 +4,6 @@ Exe - - - - diff --git a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj index 64b475b13..38cdefaba 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj +++ b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj @@ -20,7 +20,6 @@ - From 70e510421b6d69d4d37eacd04404ac06ad4f9cb2 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 29 Mar 2022 09:02:11 -0700 Subject: [PATCH 201/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 29d5fdae3..b32b80bf4 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.6.2 - 3.6.2.0 - 3.6.2.0 + 3.6.3 + 3.6.3.0 + 3.6.3.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.6.2 + 3.6.3 From b0d67558e2879848a211612b2abd085cdf0c4d2f Mon Sep 17 00:00:00 2001 From: Luis Fernando Bertucci Date: Wed, 22 Jun 2022 11:22:12 -0300 Subject: [PATCH 202/342] Added 'ProceedOnCancel' to WorkflowCore.DSL during load definition on convert steps --- src/WorkflowCore.DSL/Models/v1/StepSourceV1.cs | 5 +++-- src/WorkflowCore.DSL/Services/DefinitionLoader.cs | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/WorkflowCore.DSL/Models/v1/StepSourceV1.cs b/src/WorkflowCore.DSL/Models/v1/StepSourceV1.cs index fb67ba449..07480225a 100644 --- a/src/WorkflowCore.DSL/Models/v1/StepSourceV1.cs +++ b/src/WorkflowCore.DSL/Models/v1/StepSourceV1.cs @@ -7,7 +7,7 @@ namespace WorkflowCore.Models.DefinitionStorage.v1 public class StepSourceV1 { public string StepType { get; set; } - + public string Id { get; set; } public string Name { get; set; } @@ -29,8 +29,9 @@ public class StepSourceV1 public ExpandoObject Inputs { get; set; } = new ExpandoObject(); public Dictionary Outputs { get; set; } = new Dictionary(); - + public Dictionary SelectNextStep { get; set; } = new Dictionary(); + public bool ProceedOnCancel { get; set; } = false; } } diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index 90b830990..ef7fadc9a 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -101,6 +101,7 @@ private WorkflowStepCollection ConvertSteps(ICollection source, Ty targetStep.ErrorBehavior = nextStep.ErrorBehavior; targetStep.RetryInterval = nextStep.RetryInterval; targetStep.ExternalId = $"{nextStep.Id}"; + targetStep.ProceedOnCancel = nextStep.ProceedOnCancel; AttachInputs(nextStep, dataType, stepType, targetStep); AttachOutputs(nextStep, dataType, stepType, targetStep); From 3266b42a79a86edba62946491eaa3e0cd2be1fbe Mon Sep 17 00:00:00 2001 From: Luis Fernando Bertucci Date: Wed, 22 Jun 2022 12:48:36 -0300 Subject: [PATCH 203/342] Adjusts tests to cover the new WorkflowCore.DSL definition loader property 'ProceedOnCancel' --- .../Scenarios/StoredJsonScenario.cs | 6 +++++- .../Scenarios/StoredYamlScenario.cs | 1 + .../DataTypes/CounterBoard.cs | 1 + .../stored-definition.json | 20 +++++++++++++++++++ .../stored-definition.yaml | 15 ++++++++++++++ .../stored-dynamic-definition.json | 20 +++++++++++++++++++ .../stored-dynamic-definition.yaml | 15 ++++++++++++++ 7 files changed, 77 insertions(+), 1 deletion(-) diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs index cbd04a40a..383eb39a4 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/StoredJsonScenario.cs @@ -31,6 +31,7 @@ public void should_execute_branch1() data.Counter6.Should().Be(1); data.Counter7.Should().Be(1); data.Counter8.Should().Be(0); + data.Counter10.Should().Be(1); } [Fact(DisplayName = "Execute branch 2")] @@ -50,6 +51,7 @@ public void should_execute_branch2() data.Counter6.Should().Be(1); data.Counter7.Should().Be(0); data.Counter8.Should().Be(1); + data.Counter10.Should().Be(1); } [Fact] @@ -64,7 +66,8 @@ public void should_execute_json_workflow_with_dynamic_data() ["Counter3"] = 0, ["Counter4"] = 0, ["Counter5"] = 0, - ["Counter6"] = 0 + ["Counter6"] = 0, + ["Counter10"] = 0 }; var workflowId = StartWorkflow(TestAssets.Utils.GetTestDefinitionDynamicJson(), initialData); @@ -79,6 +82,7 @@ public void should_execute_json_workflow_with_dynamic_data() data["Counter4"].Should().Be(1); data["Counter5"].Should().Be(0); data["Counter6"].Should().Be(1); + data["Counter10"].Should().Be(1); } } } diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs index 449a6c855..95243ff03 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/StoredYamlScenario.cs @@ -29,6 +29,7 @@ public void should_execute_yaml_workflow() data.Counter4.Should().Be(1); data.Counter5.Should().Be(0); data.Counter6.Should().Be(1); + data.Counter10.Should().Be(1); } } } diff --git a/test/WorkflowCore.TestAssets/DataTypes/CounterBoard.cs b/test/WorkflowCore.TestAssets/DataTypes/CounterBoard.cs index eec59ecd6..a93b43585 100644 --- a/test/WorkflowCore.TestAssets/DataTypes/CounterBoard.cs +++ b/test/WorkflowCore.TestAssets/DataTypes/CounterBoard.cs @@ -13,6 +13,7 @@ public class CounterBoard public int Counter7 { get; set; } public int Counter8 { get; set; } public int Counter9 { get; set; } + public int Counter10 { get; set; } public bool Flag1 { get; set; } public bool Flag2 { get; set; } public bool Flag3 { get; set; } diff --git a/test/WorkflowCore.TestAssets/stored-definition.json b/test/WorkflowCore.TestAssets/stored-definition.json index 1db3a9174..7c77806b3 100644 --- a/test/WorkflowCore.TestAssets/stored-definition.json +++ b/test/WorkflowCore.TestAssets/stored-definition.json @@ -58,6 +58,26 @@ "Inputs": { "Value": "data.Counter5" }, "Outputs": { "Counter5": "step.Value" } } + ], + [ + { + "Id": "Step3.3.1", + "StepType": "WorkflowCore.Primitives.WaitFor, WorkflowCore", + "NextStepId": "Step3.3.2", + "CancelCondition": "data.Flag2", + "ProceedOnCancel": true, + "Inputs": { + "EventName": "\"Event1\"", + "EventKey": "\"Key1\"", + "EffectiveDate": "DateTime.Now" + } + }, + { + "Id": "Step3.3.2", + "StepType": "WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets", + "Inputs": { "Value": "data.Counter10" }, + "Outputs": { "Counter10": "step.Value" } + } ] ] }, diff --git a/test/WorkflowCore.TestAssets/stored-definition.yaml b/test/WorkflowCore.TestAssets/stored-definition.yaml index f01efb07b..e469b1e88 100644 --- a/test/WorkflowCore.TestAssets/stored-definition.yaml +++ b/test/WorkflowCore.TestAssets/stored-definition.yaml @@ -50,6 +50,21 @@ Steps: Value: data.Counter5 Outputs: Counter5: step.Value + - - Id: Step3.3.1 + StepType: WorkflowCore.Primitives.WaitFor, WorkflowCore + NextStepId: Step3.3.2 + CancelCondition: data.Flag2 + ProceedOnCancel: true + Inputs: + EventName: '"Event1"' + EventKey: '"Key1"' + EffectiveDate: DateTime.Now + - Id: Step3.3.2 + StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets + Inputs: + Value: data.Counter10 + Outputs: + Counter10: step.Value - Id: Step4 StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets Inputs: diff --git a/test/WorkflowCore.TestAssets/stored-dynamic-definition.json b/test/WorkflowCore.TestAssets/stored-dynamic-definition.json index dc572f8af..8c6a10dbe 100644 --- a/test/WorkflowCore.TestAssets/stored-dynamic-definition.json +++ b/test/WorkflowCore.TestAssets/stored-dynamic-definition.json @@ -57,6 +57,26 @@ "Inputs": { "Value": "data[\"Counter5\"]" }, "Outputs": { "Counter5": "step.Value" } } + ], + [ + { + "Id": "Step3.3.1", + "StepType": "WorkflowCore.Primitives.WaitFor, WorkflowCore", + "NextStepId": "Step3.3.2", + "CancelCondition": "object.Equals(data[\"Flag2\"], true)", + "ProceedOnCancel": true, + "Inputs": { + "EventName": "\"Event1\"", + "EventKey": "\"Key1\"", + "EffectiveDate": "DateTime.Now" + } + }, + { + "Id": "Step3.3.2", + "StepType": "WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets", + "Inputs": { "Value": "data[\"Counter10\"]" }, + "Outputs": { "Counter10": "step.Value" } + } ] ] }, diff --git a/test/WorkflowCore.TestAssets/stored-dynamic-definition.yaml b/test/WorkflowCore.TestAssets/stored-dynamic-definition.yaml index 6c38cd67f..9888be21e 100644 --- a/test/WorkflowCore.TestAssets/stored-dynamic-definition.yaml +++ b/test/WorkflowCore.TestAssets/stored-dynamic-definition.yaml @@ -50,6 +50,21 @@ Steps: Value: data.Counter5 Outputs: Counter5: step.Value + - - Id: Step3.3.1 + StepType: WorkflowCore.Primitives.WaitFor, WorkflowCore + NextStepId: Step3.3.2 + CancelCondition: data.Flag2 + ProceedOnCancel: true + Inputs: + EventName: '"Event1"' + EventKey: '"Key1"' + EffectiveDate: DateTime.Now + - Id: Step3.3.2 + StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets + Inputs: + Value: data.Counter10 + Outputs: + Counter10: step.Value - Id: Step4 StepType: WorkflowCore.TestAssets.Steps.Counter, WorkflowCore.TestAssets Inputs: From 6d77790dc1053aeb6f876d466f97c41e8c878ca8 Mon Sep 17 00:00:00 2001 From: Luis Fernando Bertucci Date: Wed, 22 Jun 2022 13:20:07 -0300 Subject: [PATCH 204/342] Changed to consider .NET Core in MySql provider --- src/providers/WorkflowCore.Persistence.MySQL/MysqlContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Persistence.MySQL/MysqlContext.cs b/src/providers/WorkflowCore.Persistence.MySQL/MysqlContext.cs index dc49617fd..2b65f640d 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/MysqlContext.cs +++ b/src/providers/WorkflowCore.Persistence.MySQL/MysqlContext.cs @@ -23,7 +23,7 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) base.OnConfiguring(optionsBuilder); #if NETSTANDARD2_0 optionsBuilder.UseMySql(_connectionString, _mysqlOptionsAction); -#elif NETSTANDARD2_1_OR_GREATER +#elif NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER optionsBuilder.UseMySql(_connectionString, ServerVersion.AutoDetect(_connectionString), _mysqlOptionsAction); #endif } From b4473806372dcc8ff1038e25c47caa8f0a85268a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Jun 2022 20:35:00 +0000 Subject: [PATCH 205/342] Bump Newtonsoft.Json in /src/providers/WorkflowCore.Providers.AWS Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 12.0.1 to 13.0.1. - [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases) - [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/12.0.1...13.0.1) --- updated-dependencies: - dependency-name: Newtonsoft.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- src/WorkflowCore/WorkflowCore.csproj | 2 +- .../WorkflowCore.Providers.AWS.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 0a238b8aa..bb567d87c 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -19,7 +19,7 @@ - + diff --git a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj index 5600452a2..4ea4a1ed8 100644 --- a/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj +++ b/src/providers/WorkflowCore.Providers.AWS/WorkflowCore.Providers.AWS.csproj @@ -18,7 +18,7 @@ - + From 69a37c2416dc20e308c6e9444e2db2613480115e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Jun 2022 23:27:49 +0000 Subject: [PATCH 206/342] Bump Newtonsoft.Json from 12.0.3 to 13.0.1 in /src/WorkflowCore.DSL Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 12.0.3 to 13.0.1. - [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases) - [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/12.0.3...13.0.1) --- updated-dependencies: - dependency-name: Newtonsoft.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- src/WorkflowCore.DSL/WorkflowCore.DSL.csproj | 2 +- src/WorkflowCore/WorkflowCore.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj b/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj index 1a0130fc9..b3ce61cef 100644 --- a/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj +++ b/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index 0a238b8aa..bb567d87c 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -19,7 +19,7 @@ - + From b276caa1c5995af800d849119604fdb05c5c3461 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jun 2022 02:03:05 +0000 Subject: [PATCH 207/342] Bump Newtonsoft.Json in /src/samples/WebApiSample/WebApiSample Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 12.0.1 to 13.0.1. - [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases) - [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/12.0.1...13.0.1) --- updated-dependencies: - dependency-name: Newtonsoft.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- src/samples/WebApiSample/WebApiSample/WebApiSample.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/samples/WebApiSample/WebApiSample/WebApiSample.csproj b/src/samples/WebApiSample/WebApiSample/WebApiSample.csproj index 3290c0dbf..133f705b4 100644 --- a/src/samples/WebApiSample/WebApiSample/WebApiSample.csproj +++ b/src/samples/WebApiSample/WebApiSample/WebApiSample.csproj @@ -14,7 +14,7 @@ - + From da0c23a9febcf4660bd46f22d1cfcead8d9c478b Mon Sep 17 00:00:00 2001 From: Eugene Andrukh Date: Thu, 23 Jun 2022 17:06:02 +0300 Subject: [PATCH 208/342] Do not push duplicates to Redis queue, simulate unique list behavior --- .../Services/RedisQueueProvider.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisQueueProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisQueueProvider.cs index 460f3d741..347c699b6 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisQueueProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisQueueProvider.cs @@ -36,7 +36,13 @@ public async Task QueueWork(string id, QueueType queue) if (_redis == null) throw new InvalidOperationException(); - await _redis.ListRightPushAsync(GetQueueName(queue), id, When.Always); + var queueName = GetQueueName(queue); + + var insertResult = await _redis.ListInsertBeforeAsync(queueName, id, id); + if (insertResult == -1 || insertResult == 0) + await _redis.ListRightPushAsync(queueName, id, When.Always); + else + await _redis.ListRemoveAsync(queueName, id, 1); } public async Task DequeueWork(QueueType queue, CancellationToken cancellationToken) From bb63980f804c83f9a04f9e2ca999f42bd39c57f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jun 2022 18:37:43 +0000 Subject: [PATCH 209/342] Bump Newtonsoft.Json Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 12.0.1 to 13.0.1. - [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases) - [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/12.0.1...13.0.1) --- updated-dependencies: - dependency-name: Newtonsoft.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .../WorkflowCore.Persistence.EntityFramework.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index bb07fffd3..6ab835915 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -31,7 +31,7 @@ - + From 2be0e5d2075c2164c0a60bd64f3b6e05d0f0a3bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jun 2022 18:37:58 +0000 Subject: [PATCH 210/342] Bump Newtonsoft.Json in /src/providers/WorkflowCore.Persistence.MongoDB Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 12.0.1 to 13.0.1. - [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases) - [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/12.0.1...13.0.1) --- updated-dependencies: - dependency-name: Newtonsoft.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .../WorkflowCore.Persistence.MongoDB.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj index 13df8d4aa..5d395eee9 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj +++ b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj @@ -23,7 +23,7 @@ - + From 4864e0ac3db9d99369e8061f711110e35a0e66d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jun 2022 18:38:10 +0000 Subject: [PATCH 211/342] Bump Newtonsoft.Json in /test/WorkflowCore.TestAssets Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 12.0.1 to 13.0.1. - [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases) - [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/12.0.1...13.0.1) --- updated-dependencies: - dependency-name: Newtonsoft.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj index 73bd5b39d..4530229d1 100644 --- a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj +++ b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj @@ -40,7 +40,7 @@ - + From 0cd378da79366d994c163f51f1d1353d1c79425c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jun 2022 18:38:11 +0000 Subject: [PATCH 212/342] Bump Newtonsoft.Json Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 12.0.1 to 13.0.1. - [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases) - [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/12.0.1...13.0.1) --- updated-dependencies: - dependency-name: Newtonsoft.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .../WorkflowCore.QueueProviders.RabbitMQ.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj index 48041387f..3ef1064ae 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj @@ -22,7 +22,7 @@ - + From 8eb3e2792412d8e2824c05c9235caf5bc08895aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Jun 2022 18:38:40 +0000 Subject: [PATCH 213/342] Bump Newtonsoft.Json in /src/providers/WorkflowCore.Providers.Redis Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 12.0.1 to 13.0.1. - [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases) - [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/12.0.1...13.0.1) --- updated-dependencies: - dependency-name: Newtonsoft.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .../WorkflowCore.Providers.Redis.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj b/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj index e35b091ff..b1cc0aa97 100644 --- a/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj +++ b/src/providers/WorkflowCore.Providers.Redis/WorkflowCore.Providers.Redis.csproj @@ -11,7 +11,7 @@ - + From 6840d90b7b9d07cdf4faf54c6995961e3f534157 Mon Sep 17 00:00:00 2001 From: Eugene Andrukh Date: Thu, 23 Jun 2022 17:34:41 +0300 Subject: [PATCH 214/342] Add prefix to RedisLockProvider #1044 --- .../ServiceCollectionExtensions.cs | 4 ++-- .../Services/RedisLockProvider.cs | 22 ++++++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/providers/WorkflowCore.Providers.Redis/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.Redis/ServiceCollectionExtensions.cs index 514ba21a3..27594cfac 100644 --- a/src/providers/WorkflowCore.Providers.Redis/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.Redis/ServiceCollectionExtensions.cs @@ -13,9 +13,9 @@ public static WorkflowOptions UseRedisQueues(this WorkflowOptions options, strin return options; } - public static WorkflowOptions UseRedisLocking(this WorkflowOptions options, string connectionString) + public static WorkflowOptions UseRedisLocking(this WorkflowOptions options, string connectionString, string prefix = null) { - options.UseDistributedLockManager(sp => new RedisLockProvider(connectionString, sp.GetService())); + options.UseDistributedLockManager(sp => new RedisLockProvider(connectionString, prefix, sp.GetService())); return options; } diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisLockProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisLockProvider.cs index 469ca2763..f71a1c323 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisLockProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisLockProvider.cs @@ -14,15 +14,17 @@ namespace WorkflowCore.Providers.Redis.Services public class RedisLockProvider : IDistributedLockProvider { private readonly ILogger _logger; - private readonly string _connectionString; + private readonly string _connectionString; + private readonly string _prefix; private IConnectionMultiplexer _multiplexer; private RedLockFactory _redlockFactory; private readonly TimeSpan _lockTimeout = TimeSpan.FromMinutes(1); private readonly List ManagedLocks = new List(); - public RedisLockProvider(string connectionString, ILoggerFactory logFactory) + public RedisLockProvider(string connectionString, string prefix, ILoggerFactory logFactory) { _connectionString = connectionString; + _prefix = prefix; _logger = logFactory.CreateLogger(GetType()); } @@ -31,7 +33,7 @@ public async Task AcquireLock(string Id, CancellationToken cancellationTok if (_redlockFactory == null) throw new InvalidOperationException(); - var redLock = await _redlockFactory.CreateLockAsync(Id, _lockTimeout); + var redLock = await _redlockFactory.CreateLockAsync(GetResource(Id), _lockTimeout); if (redLock.IsAcquired) { @@ -50,11 +52,13 @@ public Task ReleaseLock(string Id) if (_redlockFactory == null) throw new InvalidOperationException(); + var resource = GetResource(Id); + lock (ManagedLocks) { foreach (var redLock in ManagedLocks) { - if (redLock.Resource == Id) + if (redLock.Resource == resource) { redLock.Dispose(); ManagedLocks.Remove(redLock); @@ -77,7 +81,15 @@ public async Task Stop() _redlockFactory?.Dispose(); await _multiplexer.CloseAsync(); _multiplexer = null; - + + } + + private string GetResource(string key) + { + if (string.IsNullOrEmpty(_prefix)) + return key; + + return $"{_prefix}:{key}"; } } } From a9fb674056279c7351ed9fc7474c072359b5f504 Mon Sep 17 00:00:00 2001 From: afroze9 Date: Sun, 3 Jul 2022 07:55:42 +0500 Subject: [PATCH 215/342] Added CosmosClientOptions to UseCosmosDbPersistence method and CosmosClientFactory constructor. --- .../ServiceCollectionExtensions.cs | 8 +++++--- .../Services/CosmosClientFactory.cs | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs index 0aa1963e4..d6aec277d 100644 --- a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Azure.Cosmos; +using Microsoft.Extensions.Logging; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Providers.Azure.Interface; @@ -31,14 +32,15 @@ public static WorkflowOptions UseCosmosDbPersistence( this WorkflowOptions options, string connectionString, string databaseId, - CosmosDbStorageOptions cosmosDbStorageOptions = null) + CosmosDbStorageOptions cosmosDbStorageOptions = null, + CosmosClientOptions clientOptions = null) { if (cosmosDbStorageOptions == null) { cosmosDbStorageOptions = new CosmosDbStorageOptions(); } - options.Services.AddSingleton(sp => new CosmosClientFactory(connectionString)); + options.Services.AddSingleton(sp => new CosmosClientFactory(connectionString, clientOptions)); options.Services.AddTransient(sp => new CosmosDbProvisioner(sp.GetService(), cosmosDbStorageOptions)); options.Services.AddSingleton(sp => new WorkflowPurger(sp.GetService(), databaseId, cosmosDbStorageOptions)); options.UsePersistence(sp => new CosmosDbPersistenceProvider(sp.GetService(), databaseId, sp.GetService(), cosmosDbStorageOptions)); diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs index 9cb4cc572..ac5dc7f4a 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs @@ -10,9 +10,9 @@ public class CosmosClientFactory : ICosmosClientFactory, IDisposable private CosmosClient _client; - public CosmosClientFactory(string connectionString) + public CosmosClientFactory(string connectionString, CosmosClientOptions clientOptions = null) { - _client = new CosmosClient(connectionString); + _client = new CosmosClient(connectionString, clientOptions); } public CosmosClient GetCosmosClient() From 8fa1fb7c8f566aadce67535f26fb37268660522b Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 5 Jul 2022 14:39:14 -0700 Subject: [PATCH 216/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index b32b80bf4..30816a3b6 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.6.3 - 3.6.3.0 - 3.6.3.0 + 3.6.4 + 3.6.4.0 + 3.6.4.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.6.3 + 3.6.4 From 60cfe3dae2bba6ea656e19b64ec63088e1af675a Mon Sep 17 00:00:00 2001 From: Pavel Gorbenko Date: Tue, 26 Jul 2022 17:36:46 +0400 Subject: [PATCH 217/342] the names of the fields in the logs have been changed --- .../Services/BackgroundTasks/EventConsumer.cs | 4 ++-- .../Services/BackgroundTasks/RunnablePoller.cs | 4 ++-- .../Services/BackgroundTasks/WorkflowConsumer.cs | 6 +++--- src/WorkflowCore/Services/WorkflowController.cs | 4 ++-- src/WorkflowCore/Services/WorkflowExecutor.cs | 12 ++++++------ 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs index dd7323b01..26e630ea5 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/EventConsumer.cs @@ -114,7 +114,7 @@ private async Task SeedSubscription(Event evt, EventSubscription sub, Hash if (!await _lockProvider.AcquireLock(sub.WorkflowId, cancellationToken)) { - Logger.LogInformation("Workflow locked {0}", sub.WorkflowId); + Logger.LogInformation("Workflow locked {WorkflowId}", sub.WorkflowId); return false; } @@ -151,4 +151,4 @@ private async Task SeedSubscription(Event evt, EventSubscription sub, Hash } } } -} +} \ No newline at end of file diff --git a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs index fcd2abd92..29b76837c 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs @@ -94,7 +94,7 @@ await _persistenceStore.ScheduleCommand(new ScheduledCommand() _logger.LogDebug($"Got greylisted workflow {item}"); continue; } - _logger.LogDebug("Got runnable instance {0}", item); + _logger.LogDebug("Got runnable instance {Item}", item); _greylist.Add($"wf:{item}"); await _queueProvider.QueueWork(item, QueueType.Workflow); } @@ -218,4 +218,4 @@ await _persistenceStore.ProcessCommands(new DateTimeOffset(_dateTimeProvider.Utc } } } -} +} \ No newline at end of file diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index b3dd4aa0b..2d8cf257c 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -33,7 +33,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance { if (!await _lockProvider.AcquireLock(itemId, cancellationToken)) { - Logger.LogInformation("Workflow locked {0}", itemId); + Logger.LogInformation("Workflow locked {ItemId}", itemId); return; } @@ -101,7 +101,7 @@ await _persistenceStore.ScheduleCommand(new ScheduledCommand() private async Task SubscribeEvent(EventSubscription subscription, IPersistenceProvider persistenceStore, CancellationToken cancellationToken) { //TODO: move to own class - Logger.LogDebug("Subscribing to event {0} {1} for workflow {2} step {3}", subscription.EventName, subscription.EventKey, subscription.WorkflowId, subscription.StepId); + Logger.LogDebug("Subscribing to event {EventName} {EventKey} for workflow {WorkflowId} step {StepId}", subscription.EventName, subscription.EventKey, subscription.WorkflowId, subscription.StepId); await persistenceStore.CreateEventSubscription(subscription, cancellationToken); if (subscription.EventName != Event.EventTypeActivity) @@ -169,4 +169,4 @@ private async void FutureQueue(WorkflowInstance workflow, CancellationToken canc } } } -} +} \ No newline at end of file diff --git a/src/WorkflowCore/Services/WorkflowController.cs b/src/WorkflowCore/Services/WorkflowController.cs index 6edb63aa7..79272e084 100755 --- a/src/WorkflowCore/Services/WorkflowController.cs +++ b/src/WorkflowCore/Services/WorkflowController.cs @@ -107,7 +107,7 @@ await _eventHub.PublishNotification(new WorkflowStarted public async Task PublishEvent(string eventName, string eventKey, object eventData, DateTime? effectiveDate = null) { - _logger.LogDebug("Creating event {0} {1}", eventName, eventKey); + _logger.LogDebug("Creating event {EventName} {EventKey}", eventName, eventKey); Event evt = new Event(); if (effectiveDate.HasValue) @@ -241,4 +241,4 @@ public void RegisterWorkflow() _registry.RegisterWorkflow(wf); } } -} +} \ No newline at end of file diff --git a/src/WorkflowCore/Services/WorkflowExecutor.cs b/src/WorkflowCore/Services/WorkflowExecutor.cs index 145f02d41..da3e9cd85 100755 --- a/src/WorkflowCore/Services/WorkflowExecutor.cs +++ b/src/WorkflowCore/Services/WorkflowExecutor.cs @@ -47,7 +47,7 @@ public async Task Execute(WorkflowInstance workflow, Can var def = _registry.GetDefinition(workflow.WorkflowDefinitionId, workflow.Version); if (def == null) { - _logger.LogError("Workflow {0} version {1} is not registered", workflow.WorkflowDefinitionId, workflow.Version); + _logger.LogError("Workflow {WorkflowDefinitionId} version {Version} is not registered", workflow.WorkflowDefinitionId, workflow.Version); return wfResult; } @@ -61,7 +61,7 @@ public async Task Execute(WorkflowInstance workflow, Can var step = def.Steps.FindById(pointer.StepId); if (step == null) { - _logger.LogError("Unable to find step {0} in workflow definition", pointer.StepId); + _logger.LogError("Unable to find step {StepId} in workflow definition", pointer.StepId); pointer.SleepUntil = _datetimeProvider.UtcNow.Add(_options.ErrorRetryInterval); wfResult.Errors.Add(new ExecutionError { @@ -83,7 +83,7 @@ public async Task Execute(WorkflowInstance workflow, Can } catch (Exception ex) { - _logger.LogError(ex, "Workflow {0} raised error on step {1} Message: {2}", workflow.Id, pointer.StepId, ex.Message); + _logger.LogError(ex, "Workflow {WorkflowId} raised error on step {StepId} Message: {Message}", workflow.Id, pointer.StepId, ex.Message); wfResult.Errors.Add(new ExecutionError { WorkflowId = workflow.Id, @@ -158,14 +158,14 @@ private async Task ExecuteStep(WorkflowInstance workflow, WorkflowStep step, Exe using (var scope = _scopeProvider.CreateScope(context)) { - _logger.LogDebug("Starting step {0} on workflow {1}", step.Name, workflow.Id); + _logger.LogDebug("Starting step {StepName} on workflow {WorkflowId}", step.Name, workflow.Id); IStepBody body = step.ConstructBody(scope.ServiceProvider); var stepExecutor = scope.ServiceProvider.GetRequiredService(); if (body == null) { - _logger.LogError("Unable to construct step body {0}", step.BodyType.ToString()); + _logger.LogError("Unable to construct step body {BodyType}", step.BodyType.ToString()); pointer.SleepUntil = _datetimeProvider.UtcNow.Add(_options.ErrorRetryInterval); wfResult.Errors.Add(new ExecutionError { @@ -275,4 +275,4 @@ private async Task DetermineNextExecutionTime(WorkflowInstance workflow, Workflo }); } } -} +} \ No newline at end of file From 4eb025c00bdb531bc98768759e59c8a32e67193f Mon Sep 17 00:00:00 2001 From: badihi Date: Mon, 1 Aug 2022 12:45:02 +0430 Subject: [PATCH 218/342] Fixes a bug that occures when a compensation is nested in a branch --- .../FluentBuilders/WorkflowBuilder.cs | 10 +++ .../ForeachWithCompensationScenario.cs | 69 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 test/WorkflowCore.IntegrationTests/Scenarios/ForeachWithCompensationScenario.cs diff --git a/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs b/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs index 98788fa0c..967339967 100644 --- a/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs +++ b/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs @@ -84,6 +84,11 @@ public void AttachBranch(IWorkflowBuilder branch) if (step2.Children[i] == oldId) step2.Children[i] = step.Id; } + + if (step2.CompensationStepId == oldId) + { + step2.CompensationStepId = step.Id; + } } } @@ -104,6 +109,11 @@ public void AttachBranch(IWorkflowBuilder branch) if (step2.Children[i] == oldId) step2.Children[i] = step.Id; } + + if (step2.CompensationStepId == oldId) + { + step2.CompensationStepId = step.Id; + } } } diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ForeachWithCompensationScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ForeachWithCompensationScenario.cs new file mode 100644 index 000000000..144774fcb --- /dev/null +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ForeachWithCompensationScenario.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using WorkflowCore.Interface; +using WorkflowCore.Models; +using Xunit; +using FluentAssertions; +using WorkflowCore.Testing; + +namespace WorkflowCore.IntegrationTests.Scenarios +{ + public class ForeachWithCompensationScenario : WorkflowTest + { + internal static int Step1Ticker = 0; + internal static int Step2Ticker = 0; + internal static int Step3Ticker = 0; + internal static int CompensateTicker = 0; + + public class MyDataClass + { + } + + public class ForeachWorkflow : IWorkflow + { + public string Id => "ForeachWithCompensationWorkflow"; + public int Version => 1; + public void Build(IWorkflowBuilder builder) + { + builder + .StartWith(data => { + Step1Ticker++; + }) + .Then(data => { + Step2Ticker++; + }) + .ForEach(step => new List { 1 }) + .Do(then => then + .Decide(data => 1) + .Branch(1, builder.CreateBranch() + .StartWith(data => { + Step3Ticker++; + throw new Exception(); + }) + .CompensateWithSequence(builder => builder.StartWith(_ => { + CompensateTicker++; + }))) + ); + } + } + + public ForeachWithCompensationScenario() + { + Setup(); + } + + [Fact] + public void Scenario() + { + var workflowId = StartWorkflow(new MyDataClass()); + WaitForWorkflowToComplete(workflowId, TimeSpan.FromSeconds(30)); + + Step1Ticker.Should().Be(1); + Step2Ticker.Should().Be(1); + Step3Ticker.Should().Be(1); + CompensateTicker.Should().Be(1); + GetStatus(workflowId).Should().Be(WorkflowStatus.Complete); + UnhandledStepErrors.Count.Should().Be(1); + } + } +} From 202e7d36826bda9ee73092736c26cb38ffa9a7c0 Mon Sep 17 00:00:00 2001 From: Viktor Shevchenko Date: Fri, 5 Aug 2022 14:36:33 +0300 Subject: [PATCH 219/342] Fixed reliability of WorkflowConsumer when persisting workflow --- .../Persistence/IWorkflowRepository.cs | 2 + .../BackgroundTasks/WorkflowConsumer.cs | 6 +- .../MemoryPersistenceProvider.cs | 19 ++++++ .../TransientMemoryPersistenceProvider.cs | 10 +++ .../EntityFrameworkPersistenceProvider.cs | 26 ++++++++ .../Services/MongoPersistenceProvider.cs | 11 ++++ .../Services/RavendbPersistenceProvider.cs | 41 +++++++++--- .../Services/DynamoPersistenceProvider.cs | 37 +++++++++++ .../Services/CosmosDbPersistenceProvider.cs | 10 +++ .../Services/RedisPersistenceProvider.cs | 10 +++ .../BasePersistenceFixture.cs | 66 +++++++++++++++++++ 11 files changed, 223 insertions(+), 15 deletions(-) diff --git a/src/WorkflowCore/Interface/Persistence/IWorkflowRepository.cs b/src/WorkflowCore/Interface/Persistence/IWorkflowRepository.cs index 1da4275cd..09842af7a 100644 --- a/src/WorkflowCore/Interface/Persistence/IWorkflowRepository.cs +++ b/src/WorkflowCore/Interface/Persistence/IWorkflowRepository.cs @@ -12,6 +12,8 @@ public interface IWorkflowRepository Task PersistWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default); + Task PersistWorkflow(WorkflowInstance workflow, List subscriptions, CancellationToken cancellationToken = default); + Task> GetRunnableInstances(DateTime asAt, CancellationToken cancellationToken = default); [Obsolete] diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index b3dd4aa0b..ce917e41a 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -55,7 +55,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance finally { WorkflowActivity.Enrich(result); - await _persistenceStore.PersistWorkflow(workflow, cancellationToken); + await _persistenceStore.PersistWorkflow(workflow, result.Subscriptions, cancellationToken); await QueueProvider.QueueWork(itemId, QueueType.Index); _greylist.Remove($"wf:{itemId}"); } @@ -100,10 +100,6 @@ await _persistenceStore.ScheduleCommand(new ScheduledCommand() private async Task SubscribeEvent(EventSubscription subscription, IPersistenceProvider persistenceStore, CancellationToken cancellationToken) { - //TODO: move to own class - Logger.LogDebug("Subscribing to event {0} {1} for workflow {2} step {3}", subscription.EventName, subscription.EventKey, subscription.WorkflowId, subscription.StepId); - - await persistenceStore.CreateEventSubscription(subscription, cancellationToken); if (subscription.EventName != Event.EventTypeActivity) { var events = await persistenceStore.GetEvents(subscription.EventName, subscription.EventKey, subscription.SubscribeAsOf, cancellationToken); diff --git a/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs b/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs index e983f8fd5..cb69c8791 100644 --- a/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs +++ b/src/WorkflowCore/Services/DefaultProviders/MemoryPersistenceProvider.cs @@ -46,6 +46,25 @@ public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken _ } } + public async Task PersistWorkflow(WorkflowInstance workflow, List subscriptions, CancellationToken cancellationToken = default) + { + lock (_instances) + { + var existing = _instances.First(x => x.Id == workflow.Id); + _instances.Remove(existing); + _instances.Add(workflow); + + lock (_subscriptions) + { + foreach (var subscription in subscriptions) + { + subscription.Id = Guid.NewGuid().ToString(); + _subscriptions.Add(subscription); + } + } + } + } + public async Task> GetRunnableInstances(DateTime asAt, CancellationToken _ = default) { lock (_instances) diff --git a/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs b/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs index 0a94c6f8e..31ec6dbe2 100644 --- a/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs +++ b/src/WorkflowCore/Services/DefaultProviders/TransientMemoryPersistenceProvider.cs @@ -50,6 +50,16 @@ public TransientMemoryPersistenceProvider(ISingletonMemoryProvider innerService) public Task PersistWorkflow(WorkflowInstance workflow, CancellationToken _ = default) => _innerService.PersistWorkflow(workflow); + public async Task PersistWorkflow(WorkflowInstance workflow, List subscriptions, CancellationToken cancellationToken = default) + { + await PersistWorkflow(workflow, cancellationToken); + + foreach(var subscription in subscriptions) + { + await CreateEventSubscription(subscription, cancellationToken); + } + } + public Task TerminateSubscription(string eventSubscriptionId, CancellationToken _ = default) => _innerService.TerminateSubscription(eventSubscriptionId); public Task GetSubscription(string eventSubscriptionId, CancellationToken _ = default) => _innerService.GetSubscription(eventSubscriptionId); diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs index 44798a0c9..22ba680f5 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/EntityFrameworkPersistenceProvider.cs @@ -151,6 +151,32 @@ public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken c await db.SaveChangesAsync(cancellationToken); } } + + public async Task PersistWorkflow(WorkflowInstance workflow, List subscriptions, CancellationToken cancellationToken = default) + { + using (var db = ConstructDbContext()) + { + var uid = new Guid(workflow.Id); + var existingEntity = await db.Set() + .Where(x => x.InstanceId == uid) + .Include(wf => wf.ExecutionPointers) + .ThenInclude(ep => ep.ExtensionAttributes) + .Include(wf => wf.ExecutionPointers) + .AsTracking() + .FirstAsync(cancellationToken); + + var workflowPersistable = workflow.ToPersistable(existingEntity); + + foreach (var subscription in subscriptions) + { + subscription.Id = Guid.NewGuid().ToString(); + var subscriptionPersistable = subscription.ToPersistable(); + db.Set().Add(subscriptionPersistable); + } + + await db.SaveChangesAsync(cancellationToken); + } + } public async Task TerminateSubscription(string eventSubscriptionId, CancellationToken cancellationToken = default) { diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index 06be13355..2824f9674 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -149,6 +149,17 @@ public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken c await WorkflowInstances.ReplaceOneAsync(x => x.Id == workflow.Id, workflow, cancellationToken: cancellationToken); } + public async Task PersistWorkflow(WorkflowInstance workflow, List subscriptions, CancellationToken cancellationToken = default) + { + using (var session = await _database.Client.StartSessionAsync()) + { + session.StartTransaction(); + await PersistWorkflow(workflow, cancellationToken); + await EventSubscriptions.InsertManyAsync(subscriptions, cancellationToken: cancellationToken); + await session.CommitTransactionAsync(); + } + } + public async Task> GetRunnableInstances(DateTime asAt, CancellationToken cancellationToken = default) { var now = asAt.ToUniversalTime().Ticks; diff --git a/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs index 695b8e31f..3e1d5e2ea 100644 --- a/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.RavenDB/Services/RavendbPersistenceProvider.cs @@ -1,6 +1,7 @@ using Raven.Client.Documents; using Raven.Client.Documents.Linq; using Raven.Client.Documents.Operations; +using Raven.Client.Documents.Session; using System; using System.Collections.Generic; using System.Linq; @@ -56,21 +57,41 @@ public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken c { using (var session = _database.OpenAsyncSession()) { - session.Advanced.Patch(workflow.Id, x => x.WorkflowDefinitionId, workflow.WorkflowDefinitionId); - session.Advanced.Patch(workflow.Id, x => x.Version, workflow.Version); - session.Advanced.Patch(workflow.Id, x => x.Description, workflow.Description); - session.Advanced.Patch(workflow.Id, x => x.Reference, workflow.Reference); - session.Advanced.Patch(workflow.Id, x => x.ExecutionPointers, workflow.ExecutionPointers); - session.Advanced.Patch(workflow.Id, x => x.NextExecution, workflow.NextExecution); - session.Advanced.Patch(workflow.Id, x => x.Status, workflow.Status); - session.Advanced.Patch(workflow.Id, x => x.Data, workflow.Data); - session.Advanced.Patch(workflow.Id, x => x.CreateTime, workflow.CreateTime); - session.Advanced.Patch(workflow.Id, x => x.CompleteTime, workflow.CompleteTime); + PatchSession(session, workflow); + await session.SaveChangesAsync(cancellationToken); + } + } + + public async Task PersistWorkflow(WorkflowInstance workflow, List subscriptions, CancellationToken cancellationToken = default) + { + using (var session = _database.OpenAsyncSession()) + { + PatchSession(session, workflow); + + foreach (var subscription in subscriptions) + { + await session.StoreAsync(subscription, cancellationToken); + } await session.SaveChangesAsync(cancellationToken); } } + private void PatchSession(IAsyncDocumentSession session, WorkflowInstance workflow) + { + session.Advanced.Patch(workflow.Id, x => x.WorkflowDefinitionId, workflow.WorkflowDefinitionId); + session.Advanced.Patch(workflow.Id, x => x.Version, workflow.Version); + session.Advanced.Patch(workflow.Id, x => x.Description, workflow.Description); + session.Advanced.Patch(workflow.Id, x => x.Reference, workflow.Reference); + session.Advanced.Patch(workflow.Id, x => x.ExecutionPointers, workflow.ExecutionPointers); + session.Advanced.Patch(workflow.Id, x => x.NextExecution, workflow.NextExecution); + session.Advanced.Patch(workflow.Id, x => x.Status, workflow.Status); + session.Advanced.Patch(workflow.Id, x => x.Data, workflow.Data); + session.Advanced.Patch(workflow.Id, x => x.CreateTime, workflow.CreateTime); + session.Advanced.Patch(workflow.Id, x => x.CompleteTime, workflow.CompleteTime); + + } + public async Task> GetRunnableInstances(DateTime asAt, CancellationToken cancellationToken = default) { var now = asAt.ToUniversalTime().Ticks; diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs index 1126b6c20..09f1dbc4c 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs @@ -61,6 +61,43 @@ public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken c var response = await _client.PutItemAsync(request, cancellationToken); } + public async Task PersistWorkflow(WorkflowInstance workflow, List subscriptions, CancellationToken cancellationToken = default) + { + var transactionWriteItemsRequest = new TransactWriteItemsRequest() + { + TransactItems = new List() + { + { + new TransactWriteItem() + { + Put = new Put() + { + TableName = $"{_tablePrefix}-{WORKFLOW_TABLE}", + Item = workflow.ToDynamoMap() + } + } + } + } + }; + + foreach(var subscription in subscriptions) + { + subscription.Id = Guid.NewGuid().ToString(); + + transactionWriteItemsRequest.TransactItems.Add(new TransactWriteItem() + { + Put = new Put() + { + TableName = $"{_tablePrefix}-{SUBCRIPTION_TABLE}", + Item = subscription.ToDynamoMap(), + ConditionExpression = "attribute_not_exists(id)" + } + }); + } + + await _client.TransactWriteItemsAsync(transactionWriteItemsRequest, cancellationToken); + } + public async Task> GetRunnableInstances(DateTime asAt, CancellationToken cancellationToken = default) { var result = new List(); diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs index 644009df2..008136494 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosDbPersistenceProvider.cs @@ -227,6 +227,16 @@ public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken c await _workflowContainer.Value.UpsertItemAsync(PersistedWorkflow.FromInstance(workflow), cancellationToken: cancellationToken); } + public async Task PersistWorkflow(WorkflowInstance workflow, List subscriptions, CancellationToken cancellationToken = default) + { + await PersistWorkflow(workflow, cancellationToken); + + foreach(var subscription in subscriptions) + { + await CreateEventSubscription(subscription, cancellationToken); + } + } + public Task ProcessCommands(DateTimeOffset asOf, Func action, CancellationToken cancellationToken = default) { throw new NotImplementedException(); diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs index cde65e2e5..6bf8df875 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs @@ -47,6 +47,16 @@ public async Task CreateNewWorkflow(WorkflowInstance workflow, Cancellat return workflow.Id; } + public async Task PersistWorkflow(WorkflowInstance workflow, List subscriptions, CancellationToken cancellationToken = default) + { + await PersistWorkflow(workflow, cancellationToken); + + foreach (var subscription in subscriptions) + { + await CreateEventSubscription(subscription, cancellationToken); + } + } + public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken _ = default) { var str = JsonConvert.SerializeObject(workflow, _serializerSettings); diff --git a/test/WorkflowCore.UnitTests/BasePersistenceFixture.cs b/test/WorkflowCore.UnitTests/BasePersistenceFixture.cs index 0afa9bd7e..9114da7b9 100644 --- a/test/WorkflowCore.UnitTests/BasePersistenceFixture.cs +++ b/test/WorkflowCore.UnitTests/BasePersistenceFixture.cs @@ -185,6 +185,72 @@ public void PersistWorkflow() var current = Subject.GetWorkflowInstance(workflowId).Result; current.ShouldBeEquivalentTo(newWorkflow); } + + [Fact] + public void PersistWorkflow_with_subscriptions() + { + var workflow = new WorkflowInstance + { + Data = new TestData { Value1 = 7 }, + Description = "My Description", + Status = WorkflowStatus.Runnable, + NextExecution = 0, + Version = 1, + WorkflowDefinitionId = "My Workflow", + CreateTime = new DateTime(2000, 1, 1).ToUniversalTime(), + ExecutionPointers = new ExecutionPointerCollection(), + Reference = Guid.NewGuid().ToString() + }; + + workflow.ExecutionPointers.Add(new ExecutionPointer + { + Id = Guid.NewGuid().ToString(), + Active = true, + StepId = 0, + Scope = new List { "1", "2", "3", "4" }, + EventName = "Event1" + }); + + workflow.ExecutionPointers.Add(new ExecutionPointer + { + Id = Guid.NewGuid().ToString(), + Active = true, + StepId = 1, + Scope = new List { "1", "2", "3", "4" }, + EventName = "Event2", + }); + + var workflowId = Subject.CreateNewWorkflow(workflow).Result; + workflow.NextExecution = 0; + + List subscriptions = new List(); + foreach (var pointer in workflow.ExecutionPointers) + { + var subscription = new EventSubscription() + { + WorkflowId = workflowId, + StepId = pointer.StepId, + ExecutionPointerId = pointer.Id, + EventName = pointer.EventName, + EventKey = workflowId, + SubscribeAsOf = DateTime.UtcNow, + SubscriptionData = "data" + }; + + subscriptions.Add(subscription); + } + + Subject.PersistWorkflow(workflow, subscriptions).Wait(); + + var current = Subject.GetWorkflowInstance(workflowId).Result; + current.ShouldBeEquivalentTo(workflow); + + foreach (var pointer in workflow.ExecutionPointers) + { + subscriptions = Subject.GetSubscriptions(pointer.EventName, workflowId, DateTime.UtcNow).Result.ToList(); + subscriptions.Should().HaveCount(1); + } + } [Fact] public void ConcurrentPersistWorkflow() From d0a2f74c4155db0f6e25f610462742e2776b690c Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 13 Aug 2022 10:39:01 -0700 Subject: [PATCH 220/342] bump version --- src/Directory.Build.props | 8 +- ...WorkflowCore.Persistence.PostgreSQL.csproj | 5 +- .../Properties/Resources.Designer.cs | 186 +++++++++--------- .../Properties/Resources.Designer.cs | 2 +- 4 files changed, 101 insertions(+), 100 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 30816a3b6..bb20f98eb 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.6.4 - 3.6.4.0 - 3.6.4.0 + 3.6.5 + 3.6.5.0 + 3.6.5.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.6.4 + 3.6.5 diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index 5ff53cd02..e321a340a 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -23,7 +23,8 @@ - + + All @@ -34,7 +35,7 @@ - + All diff --git a/test/ScratchPad/Properties/Resources.Designer.cs b/test/ScratchPad/Properties/Resources.Designer.cs index bb7355e59..6e79d8a01 100644 --- a/test/ScratchPad/Properties/Resources.Designer.cs +++ b/test/ScratchPad/Properties/Resources.Designer.cs @@ -1,93 +1,93 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace ScratchPad.Properties { - using System; - using System.Reflection; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ScratchPad.Properties.Resources", typeof(Resources).GetTypeInfo().Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to { - /// "Id": "HelloWorld", - /// "Version": 1, - /// "Description": "", - /// "DataType": "System.Object", - /// "Steps": [ - /// { - /// "Id": "Hello", - /// "StepType": "ScratchPad.HelloWorld; ScratchPad", - /// "Name": "Hello", - /// "NextStepId": "Bye", - /// "Inputs": [], - /// "Outputs": [] - /// }, - /// { - /// "Id": "Bye", - /// "StepType": "ScratchPad.GoodbyeWorld; ScratchPad", - /// "Name": "Bye" - /// } - /// ] - ///}. - /// - internal static string HelloWorld { - get { - return ResourceManager.GetString("HelloWorld", resourceCulture); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ScratchPad.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ScratchPad.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to { + /// "Id": "Test02", + /// "Version": 1, + /// "Description": "", + /// "DataType": "ScratchPad.WfData, ScratchPad", + /// "Steps": [ + /// { + /// "Id": "Hello", + /// "StepType": "ScratchPad.HelloWorld, ScratchPad", + /// "NextStepId": "decide" + /// }, + /// { + /// "Id": "decide", + /// "StepType": "WorkflowCore.Primitives.Decide, WorkflowCore", + /// "SelectNextStep": + /// { + /// "Print1": "data.Value1 == \"one\"", + /// "Print2": "data.Value1 == \"two\"" + /// } + /// }, + /// { + /// "Id": "Print1", /// [rest of string was truncated]";. + /// + internal static string HelloWorld { + get { + return ResourceManager.GetString("HelloWorld", resourceCulture); + } + } + } +} diff --git a/test/WorkflowCore.TestAssets/Properties/Resources.Designer.cs b/test/WorkflowCore.TestAssets/Properties/Resources.Designer.cs index 286c37d49..d4b47397a 100644 --- a/test/WorkflowCore.TestAssets/Properties/Resources.Designer.cs +++ b/test/WorkflowCore.TestAssets/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace WorkflowCore.TestAssets.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resources { From 4cf59daf2d410f83f4caae668f21ab33943350a5 Mon Sep 17 00:00:00 2001 From: Viktor Shevchenko Date: Sun, 14 Aug 2022 15:00:02 +0300 Subject: [PATCH 221/342] Changed method name --- src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index ce917e41a..3a6465902 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -68,7 +68,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance { foreach (var sub in result.Subscriptions) { - await SubscribeEvent(sub, _persistenceStore, cancellationToken); + await TryProcessSubscription(sub, _persistenceStore, cancellationToken); } await _persistenceStore.PersistErrors(result.Errors, cancellationToken); @@ -98,7 +98,7 @@ await _persistenceStore.ScheduleCommand(new ScheduledCommand() } - private async Task SubscribeEvent(EventSubscription subscription, IPersistenceProvider persistenceStore, CancellationToken cancellationToken) + private async Task TryProcessSubscription(EventSubscription subscription, IPersistenceProvider persistenceStore, CancellationToken cancellationToken) { if (subscription.EventName != Event.EventTypeActivity) { From 7d3bbfa86361008839686904821b54bfc7e336db Mon Sep 17 00:00:00 2001 From: Martin Dennhardt Date: Wed, 24 Aug 2022 14:56:10 +0200 Subject: [PATCH 222/342] Make QueueConsumer.Stop() idempotent Fixes #1085 --- src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs index 1476e8b96..a5392ecbb 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs @@ -53,8 +53,11 @@ public virtual void Start() public virtual void Stop() { _cancellationTokenSource.Cancel(); - DispatchTask.Wait(); - DispatchTask = null; + if (DispatchTask != null) + { + DispatchTask.Wait(); + DispatchTask = null; + } } private async Task Execute() From a74727969e005dee6b4115ab4a18581b23d587b9 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 30 Aug 2022 15:03:33 -0700 Subject: [PATCH 223/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index bb20f98eb..298e3079c 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.6.5 - 3.6.5.0 - 3.6.5.0 + 3.7.0 + 3.7.0.0 + 3.7.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.6.5 + 3.7.0 From fc3c66ade8f55bc0f97e3bd329ccec19d398ebb8 Mon Sep 17 00:00:00 2001 From: Ivan Josipovic <9521987+IvanJosipovic@users.noreply.github.com> Date: Fri, 30 Sep 2022 16:54:09 -0700 Subject: [PATCH 224/342] feat: add IStepExecutionContext to UserTask --- .../StepBuilderExtensions.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/extensions/WorkflowCore.Users/ServiceExtensions/StepBuilderExtensions.cs b/src/extensions/WorkflowCore.Users/ServiceExtensions/StepBuilderExtensions.cs index 2b337c1fd..6f3f42935 100644 --- a/src/extensions/WorkflowCore.Users/ServiceExtensions/StepBuilderExtensions.cs +++ b/src/extensions/WorkflowCore.Users/ServiceExtensions/StepBuilderExtensions.cs @@ -18,7 +18,7 @@ public static IStepBuilder UserStep(this ISte { var newStep = new UserStepContainer(); newStep.Principal = assigner; - newStep.UserPrompt = userPrompt; + newStep.UserPrompt = userPrompt; builder.WorkflowBuilder.AddStep(newStep); var stepBuilder = new StepBuilder(builder.WorkflowBuilder, newStep); @@ -64,5 +64,23 @@ public static IUserTaskBuilder UserTask(this IStepBuild return stepBuilder; } + + public static IUserTaskBuilder UserTask(this IStepBuilder builder, string userPrompt, Expression> assigner, Action> stepSetup = null) + where TStepBody : IStepBody + { + var newStep = new UserTaskStep(); + builder.WorkflowBuilder.AddStep(newStep); + var stepBuilder = new UserTaskBuilder(builder.WorkflowBuilder, newStep); + stepBuilder.Input(step => step.AssignedPrincipal, assigner); + stepBuilder.Input(step => step.Prompt, data => userPrompt); + + if (stepSetup != null) + stepSetup.Invoke(stepBuilder); + + newStep.Name = newStep.Name ?? typeof(UserTask).Name; + builder.Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); + + return stepBuilder; + } } } From 717eb16f45347eddf121c2b69dfc90f95ef63f86 Mon Sep 17 00:00:00 2001 From: Ivan Josipovic <9521987+IvanJosipovic@users.noreply.github.com> Date: Fri, 30 Sep 2022 18:07:40 -0700 Subject: [PATCH 225/342] feat: add IStepExecutionContext to If When ForEach --- .../Interface/IWorkflowModifier.cs | 23 +++++- .../Services/FluentBuilders/StepBuilder.cs | 73 +++++++++++++++---- .../FluentBuilders/WorkflowBuilder.cs | 15 ++++ 3 files changed, 97 insertions(+), 14 deletions(-) diff --git a/src/WorkflowCore/Interface/IWorkflowModifier.cs b/src/WorkflowCore/Interface/IWorkflowModifier.cs index 1ecd093d0..835855e97 100644 --- a/src/WorkflowCore/Interface/IWorkflowModifier.cs +++ b/src/WorkflowCore/Interface/IWorkflowModifier.cs @@ -83,7 +83,7 @@ IStepBuilder WaitFor(string eventName, /// Resolves a collection for iterate over /// IContainerStepBuilder ForEach(Expression> collection); - + /// /// Execute a block of steps, once for each item in a collection in a RunParallel foreach /// @@ -91,6 +91,13 @@ IStepBuilder WaitFor(string eventName, /// IContainerStepBuilder ForEach(Expression> collection, Expression> runParallel); + /// + /// Execute a block of steps, once for each item in a collection in a RunParallel foreach + /// + /// Resolves a collection for iterate over + /// + IContainerStepBuilder ForEach(Expression> collection, Expression> runParallel); + /// /// Repeat a block of steps until a condition becomes true /// @@ -98,6 +105,13 @@ IStepBuilder WaitFor(string eventName, /// IContainerStepBuilder While(Expression> condition); + /// + /// Repeat a block of steps until a condition becomes true + /// + /// Resolves a condition to break out of the while loop + /// + IContainerStepBuilder While(Expression> condition); + /// /// Execute a block of steps if a condition is true /// @@ -105,6 +119,13 @@ IStepBuilder WaitFor(string eventName, /// IContainerStepBuilder If(Expression> condition); + /// + /// Execute a block of steps if a condition is true + /// + /// Resolves a condition to evaluate + /// + IContainerStepBuilder If(Expression> condition); + /// /// Configure an outcome for this step, then wire it to a sequence /// diff --git a/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs b/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs index 9cfeae852..9e41f15ca 100644 --- a/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs +++ b/src/WorkflowCore/Services/FluentBuilders/StepBuilder.cs @@ -59,7 +59,7 @@ public IStepBuilder Then(IStepBuilder newStep } public IStepBuilder Then(Func body) - { + { WorkflowStepInline newStep = new WorkflowStepInline(); newStep.Body = body; WorkflowBuilder.AddStep(newStep); @@ -100,7 +100,7 @@ public IStepOutcomeBuilder When(object outcomeValue, string label = null) var outcomeBuilder = new StepOutcomeBuilder(WorkflowBuilder, result); return outcomeBuilder; } - + public IStepBuilder Branch(object outcomeValue, IStepBuilder branch) where TStep : IStepBody { if (branch.WorkflowBuilder.Steps.Count == 0) @@ -123,10 +123,10 @@ public IStepBuilder Branch(Expression(outcomeExpression) - { + { NextStep = branch.WorkflowBuilder.Steps[0].Id }); @@ -155,7 +155,7 @@ public IStepBuilder Input(Action(action)); return this; - } + } public IStepBuilder Output(Expression> dataProperty, Expression> value) { @@ -206,7 +206,7 @@ public IStepBuilder WaitFor(string eventName, Expression End(string name) where TStep : IStepBody { var ancestor = IterateParents(Step.Id, name); @@ -294,12 +294,12 @@ public IStepBuilder Decide(Expression> expres public IContainerStepBuilder ForEach(Expression> collection) { var newStep = new WorkflowStep(); - + Expression> inputExpr = (x => x.Collection); - newStep.Inputs.Add(new MemberMapParameter(collection, inputExpr)); + newStep.Inputs.Add(new MemberMapParameter(collection, inputExpr)); WorkflowBuilder.AddStep(newStep); - var stepBuilder = new StepBuilder(WorkflowBuilder, newStep); + var stepBuilder = new StepBuilder(WorkflowBuilder, newStep); Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); @@ -324,6 +324,23 @@ public IContainerStepBuilder ForEach(Expression ForEach(Expression> collection, Expression> runParallel) + { + var newStep = new WorkflowStep(); + + Expression> inputExpr = (x => x.Collection); + newStep.Inputs.Add(new MemberMapParameter(collection, inputExpr)); + + Expression> pExpr = (x => x.RunParallel); + newStep.Inputs.Add(new MemberMapParameter(runParallel, pExpr)); + + WorkflowBuilder.AddStep(newStep); + var stepBuilder = new StepBuilder(WorkflowBuilder, newStep); + + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); + + return stepBuilder; + } public IContainerStepBuilder While(Expression> condition) { @@ -340,6 +357,21 @@ public IContainerStepBuilder While(Expression While(Expression> condition) + { + var newStep = new WorkflowStep(); + + Expression> inputExpr = (x => x.Condition); + newStep.Inputs.Add(new MemberMapParameter(condition, inputExpr)); + + WorkflowBuilder.AddStep(newStep); + var stepBuilder = new StepBuilder(WorkflowBuilder, newStep); + + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); + + return stepBuilder; + } + public IContainerStepBuilder If(Expression> condition) { var newStep = new WorkflowStep(); @@ -354,7 +386,22 @@ public IContainerStepBuilder If(Expression> con return stepBuilder; } - + + public IContainerStepBuilder If(Expression> condition) + { + var newStep = new WorkflowStep(); + + Expression> inputExpr = (x => x.Condition); + newStep.Inputs.Add(new MemberMapParameter(condition, inputExpr)); + + WorkflowBuilder.AddStep(newStep); + var stepBuilder = new StepBuilder(WorkflowBuilder, newStep); + + Step.Outcomes.Add(new ValueOutcome { NextStep = newStep.Id }); + + return stepBuilder; + } + public IContainerStepBuilder When(Expression> outcomeValue, string label = null) { var newStep = new WorkflowStep(); @@ -378,7 +425,7 @@ public IContainerStepBuilder When(Expression); } - + WorkflowBuilder.AddStep(newStep); var stepBuilder = new ReturnStepBuilder(WorkflowBuilder, newStep, switchBuilder); switchBuilder.Step.Children.Add(newStep.Id); @@ -512,10 +559,10 @@ public IStepBuilder Activity(string activityName, Expression(WorkflowBuilder, newStep); stepBuilder.Input((step) => step.ActivityName, (data) => activityName); - + if (parameters != null) stepBuilder.Input((step) => step.Parameters, parameters); - + if (effectiveDate != null) stepBuilder.Input((step) => step.EffectiveDate, effectiveDate); diff --git a/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs b/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs index 64950f46d..adc02f488 100644 --- a/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs +++ b/src/WorkflowCore/Services/FluentBuilders/WorkflowBuilder.cs @@ -241,16 +241,31 @@ public IContainerStepBuilder ForEach(Expression ForEach(Expression> collection, Expression> runParallel) + { + return Start().ForEach(collection, runParallel); + } + public IContainerStepBuilder While(Expression> condition) { return Start().While(condition); } + public IContainerStepBuilder While(Expression> condition) + { + return Start().While(condition); + } + public IContainerStepBuilder If(Expression> condition) { return Start().If(condition); } + public IContainerStepBuilder If(Expression> condition) + { + return Start().If(condition); + } + public IContainerStepBuilder When(Expression> outcomeValue, string label = null) { return ((IWorkflowModifier) Start()).When(outcomeValue, label); From 97974b2199dfbd40752bb35f4f2f191a4e0dd4b5 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Thu, 3 Nov 2022 08:44:56 -0700 Subject: [PATCH 226/342] Create FUNDING.yml --- .github/FUNDING.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..21a4c65b6 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: [danielgerlag] From 0908116cdc9c87a76c11c6d338f90ad29c107fef Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 22 Nov 2022 13:44:34 +0100 Subject: [PATCH 227/342] Fix mongodb index for GetRunnableInstances --- .../Services/MongoPersistenceProvider.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index 2824f9674..0d238ec64 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -93,8 +93,10 @@ static void CreateIndexes(MongoPersistenceProvider instance) if (!indexesCreated) { instance.WorkflowInstances.Indexes.CreateOne(new CreateIndexModel( - Builders.IndexKeys.Ascending(x => x.NextExecution), - new CreateIndexOptions {Background = true, Name = "idx_nextExec"})); + Builders.IndexKeys + .Ascending(x => x.NextExecution) + .Ascending(x => x.Status), + new CreateIndexOptions {Background = true, Name = "idx_nextExec_v2"})); instance.Events.Indexes.CreateOne(new CreateIndexModel( Builders.IndexKeys.Ascending(x => x.IsProcessed), From b227d6f3a60bcbffc3c42f6e3b71213aed554248 Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 22 Nov 2022 13:51:22 +0100 Subject: [PATCH 228/342] Disable table scan for tests --- test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs index 9ce3ce7d7..3a2c0d624 100644 --- a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs +++ b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs @@ -1,5 +1,6 @@ using System; using Docker.Testify; +using MongoDB.Bson; using MongoDB.Driver; using Xunit; @@ -23,6 +24,10 @@ public override bool TestReady() { var client = new MongoClient($"mongodb://localhost:{ExternalPort}"); client.ListDatabases(); + + var command = new BsonDocument { { "setParameter", 1 }, { "notablescan", 1 } }; + client.GetDatabase("admin").RunCommand(command); + return true; } catch From b878221866ce64bc77f26de3d6e41a09020d571a Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 22 Nov 2022 15:01:48 +0100 Subject: [PATCH 229/342] Switch postgress and mongo tests to Squadron --- .../MongoDockerSetup.cs | 41 +++++++----------- .../WorkflowCore.Tests.MongoDB.csproj | 5 ++- .../DockerSetup.cs | 43 +++++++------------ .../WorkflowCore.Tests.PostgreSQL.csproj | 5 ++- 4 files changed, 37 insertions(+), 57 deletions(-) diff --git a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs index 3a2c0d624..b7214ea73 100644 --- a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs +++ b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs @@ -1,40 +1,32 @@ using System; -using Docker.Testify; +using System.Threading.Tasks; using MongoDB.Bson; -using MongoDB.Driver; +using Squadron; using Xunit; namespace WorkflowCore.Tests.MongoDB { - public class MongoDockerSetup : DockerSetup + public class MongoDockerSetup : IAsyncLifetime { + private readonly MongoResource _mongoResource; public static string ConnectionString { get; set; } - public override string ImageName => "mongo"; - public override int InternalPort => 27017; - - public override void PublishConnectionInfo() + public MongoDockerSetup() { - ConnectionString = $"mongodb://localhost:{ExternalPort}"; + _mongoResource = new MongoResource(); } - - public override bool TestReady() + + public async Task InitializeAsync() { - try - { - var client = new MongoClient($"mongodb://localhost:{ExternalPort}"); - client.ListDatabases(); - - var command = new BsonDocument { { "setParameter", 1 }, { "notablescan", 1 } }; - client.GetDatabase("admin").RunCommand(command); - - return true; - } - catch - { - return false; - } + await _mongoResource.InitializeAsync(); + var command = new BsonDocument { { "setParameter", 1 }, { "notablescan", 1 } }; + _mongoResource.Client.GetDatabase("admin").RunCommand(command); + ConnectionString = _mongoResource.ConnectionString; + } + public Task DisposeAsync() + { + return _mongoResource.DisposeAsync(); } } @@ -42,5 +34,4 @@ public override bool TestReady() public class MongoCollection : ICollectionFixture { } - } diff --git a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj index 98fdd4ce8..048f3d994 100644 --- a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj +++ b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj @@ -24,8 +24,9 @@ - - + + + diff --git a/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs b/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs index 253493803..3f7739ee9 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs @@ -1,43 +1,31 @@ using System; -using System.Collections.Generic; -using Docker.Testify; -using Npgsql; +using System.Threading.Tasks; +using Squadron; using Xunit; namespace WorkflowCore.Tests.PostgreSQL { - public class PostgresDockerSetup : DockerSetup + public class PostgresDockerSetup : IAsyncLifetime { + private readonly PostgreSqlResource _postgreSqlResource; public static string ConnectionString { get; set; } public static string ScenarioConnectionString { get; set; } - public override string ImageName => "postgres"; - public override int InternalPort => 5432; - - private const string PostgresHostAuthMethod = "trust"; - public override IList EnvironmentVariables => new List { - $"POSTGRES_HOST_AUTH_METHOD={PostgresHostAuthMethod}" - }; - public override void PublishConnectionInfo() + public PostgresDockerSetup() { - ConnectionString = $"Server=127.0.0.1;Port={ExternalPort};Database=workflow;User Id=postgres;"; - ScenarioConnectionString = $"Server=127.0.0.1;Port={ExternalPort};Database=workflow-scenarios;User Id=postgres;"; + _postgreSqlResource = new PostgreSqlResource(); } - - public override bool TestReady() + + public async Task InitializeAsync() { - try - { - var connection = new NpgsqlConnection($"Server=127.0.0.1;Port={ExternalPort};Database=postgres;User Id=postgres;"); - connection.Open(); - connection.Close(); - return true; - } - catch - { - return false; - } + await _postgreSqlResource.InitializeAsync(); + ConnectionString = _postgreSqlResource.ConnectionString; + ScenarioConnectionString = _postgreSqlResource.ConnectionString; + } + public Task DisposeAsync() + { + return _postgreSqlResource.DisposeAsync(); } } @@ -45,5 +33,4 @@ public override bool TestReady() public class PostgresCollection : ICollectionFixture { } - } diff --git a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj index 38cdefaba..a228ea763 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj +++ b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj @@ -21,8 +21,9 @@ - - + + + From 913b486b3d4dbb90b02c8b499b2799c8e911ab26 Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 22 Nov 2022 15:03:30 +0100 Subject: [PATCH 230/342] Add mongodb tests to pipeline --- .github/workflows/dotnet.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 9a49e0237..181960023 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -27,6 +27,8 @@ jobs: run: dotnet test test/WorkflowCore.UnitTests --no-build --verbosity normal -p:ParallelizeTestCollections=false - name: Integration Tests run: dotnet test test/WorkflowCore.IntegrationTests --no-build --verbosity normal -p:ParallelizeTestCollections=false + - name: MongoDB Tests + run: dotnet test test/WorkflowCore.Tests.MongoDB --no-build --verbosity normal -p:ParallelizeTestCollections=false - name: PostgreSQL Tests run: dotnet test test/WorkflowCore.Tests.PostgreSQL --no-build --verbosity normal -p:ParallelizeTestCollections=false - name: Redis Tests From c5aac199573a410e3abe27095fa01872bf970d4d Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 22 Nov 2022 15:08:11 +0100 Subject: [PATCH 231/342] Remove table scan deactivation from tests --- test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs index b7214ea73..139fef30f 100644 --- a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs +++ b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs @@ -19,8 +19,9 @@ public MongoDockerSetup() public async Task InitializeAsync() { await _mongoResource.InitializeAsync(); - var command = new BsonDocument { { "setParameter", 1 }, { "notablescan", 1 } }; - _mongoResource.Client.GetDatabase("admin").RunCommand(command); + // TODO: Should be enabled + // var command = new BsonDocument { { "setParameter", 1 }, { "notablescan", 1 } }; + // _mongoResource.Client.GetDatabase("admin").RunCommand(command); ConnectionString = _mongoResource.ConnectionString; } From 1571e78195c05c000434bd6628d12d65821095e5 Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 22 Nov 2022 15:16:37 +0100 Subject: [PATCH 232/342] Run tests in parallel --- .github/workflows/dotnet.yml | 112 ++++++++++++++++++++++++++++++----- 1 file changed, 97 insertions(+), 15 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 181960023..8bb2947f6 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -7,10 +7,8 @@ on: branches: [ master ] jobs: - build: - + Unit-Tests: runs-on: ubuntu-latest - steps: - uses: actions/checkout@v2 - name: Setup .NET @@ -25,15 +23,99 @@ jobs: run: dotnet build --no-restore - name: Unit Tests run: dotnet test test/WorkflowCore.UnitTests --no-build --verbosity normal -p:ParallelizeTestCollections=false - - name: Integration Tests - run: dotnet test test/WorkflowCore.IntegrationTests --no-build --verbosity normal -p:ParallelizeTestCollections=false - - name: MongoDB Tests - run: dotnet test test/WorkflowCore.Tests.MongoDB --no-build --verbosity normal -p:ParallelizeTestCollections=false - - name: PostgreSQL Tests - run: dotnet test test/WorkflowCore.Tests.PostgreSQL --no-build --verbosity normal -p:ParallelizeTestCollections=false - - name: Redis Tests - run: dotnet test test/WorkflowCore.Tests.Redis --no-build --verbosity normal -p:ParallelizeTestCollections=false - - name: SQL Server Tests - run: dotnet test test/WorkflowCore.Tests.SqlServer --no-build --verbosity normal -p:ParallelizeTestCollections=false - - name: Elasticsearch Tests - run: dotnet test test/WorkflowCore.Tests.Elasticsearch --no-build --verbosity normal -p:ParallelizeTestCollections=false + Integration-Tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: | + 3.1.x + 6.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Integration Tests + run: dotnet test test/WorkflowCore.IntegrationTests --no-build --verbosity normal -p:ParallelizeTestCollections=false + MongoDB-Tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: | + 3.1.x + 6.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: MongoDB Tests + run: dotnet test test/WorkflowCore.Tests.MongoDB --no-build --verbosity normal -p:ParallelizeTestCollections=false + PostgreSQL-Tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: | + 3.1.x + 6.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: PostgreSQL Tests + run: dotnet test test/WorkflowCore.Tests.PostgreSQL --no-build --verbosity normal -p:ParallelizeTestCollections=false + Redis-Tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: | + 3.1.x + 6.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Redis Tests + run: dotnet test test/WorkflowCore.Tests.Redis --no-build --verbosity normal -p:ParallelizeTestCollections=false + SQLServer-Tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: | + 3.1.x + 6.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: SQL Server Tests + run: dotnet test test/WorkflowCore.Tests.SqlServer --no-build --verbosity normal -p:ParallelizeTestCollections=false + Elasticsearch-Tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: | + 3.1.x + 6.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Elasticsearch Tests + run: dotnet test test/WorkflowCore.Tests.Elasticsearch --no-build --verbosity normal -p:ParallelizeTestCollections=false \ No newline at end of file From a726680aea97d907185b767abde67fa126092884 Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 22 Nov 2022 15:21:07 +0100 Subject: [PATCH 233/342] Switch redis to Squadron --- .../RedisDockerSetup.cs | 32 ++++++++----------- .../WorkflowCore.Tests.Redis.csproj | 5 +-- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/test/WorkflowCore.Tests.Redis/RedisDockerSetup.cs b/test/WorkflowCore.Tests.Redis/RedisDockerSetup.cs index 91fd3e32a..0cc13c8b2 100644 --- a/test/WorkflowCore.Tests.Redis/RedisDockerSetup.cs +++ b/test/WorkflowCore.Tests.Redis/RedisDockerSetup.cs @@ -1,34 +1,29 @@ using System; -using Docker.Testify; -using StackExchange.Redis; +using System.Threading.Tasks; +using Squadron; using Xunit; namespace WorkflowCore.Tests.Redis { - public class RedisDockerSetup : DockerSetup + public class RedisDockerSetup : IAsyncLifetime { + private readonly RedisResource _redisResource; public static string ConnectionString { get; set; } - public override string ImageName => @"redis"; - public override int InternalPort => 6379; - - public override void PublishConnectionInfo() + public RedisDockerSetup() { - ConnectionString = $"localhost:{ExternalPort}"; + _redisResource = new RedisResource(); } - public override bool TestReady() + public async Task InitializeAsync() { - try - { - var multiplexer = ConnectionMultiplexer.Connect($"localhost:{ExternalPort}"); - return multiplexer.IsConnected; - } - catch - { - return false; - } + await _redisResource.InitializeAsync(); + ConnectionString = _redisResource.ConnectionString; + } + public Task DisposeAsync() + { + return _redisResource.DisposeAsync(); } } @@ -36,5 +31,4 @@ public override bool TestReady() public class RedisCollection : ICollectionFixture { } - } diff --git a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj index 0ee3705bf..ddb796d70 100644 --- a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj +++ b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj @@ -3,8 +3,9 @@ - - + + + From a6a2d153745927b8861344b4e2a1bfe49c6d01a2 Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 22 Nov 2022 15:23:44 +0100 Subject: [PATCH 234/342] Switch SQLServer tests --- .../DockerSetup.cs | 42 +++++++------------ .../WorkflowCore.Tests.SqlServer.csproj | 5 ++- 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs b/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs index b9d15ddff..147c09241 100644 --- a/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs +++ b/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs @@ -1,44 +1,31 @@ using System; -using System.Collections.Generic; -using System.Data.SqlClient; -using Docker.Testify; +using System.Threading.Tasks; +using Squadron; using Xunit; namespace WorkflowCore.Tests.SqlServer { - public class SqlDockerSetup : DockerSetup + public class SqlDockerSetup : IAsyncLifetime { + private readonly SqlServerResource _sqlServerResource; public static string ConnectionString { get; set; } public static string ScenarioConnectionString { get; set; } - public override string ImageName => "mcr.microsoft.com/mssql/server"; - public override int InternalPort => 1433; - public override TimeSpan TimeOut => TimeSpan.FromSeconds(120); - - public const string SqlPassword = "I@mJustT3st1ing"; - - public override IList EnvironmentVariables => new List {"ACCEPT_EULA=Y", $"SA_PASSWORD={SqlPassword}"}; - - public override void PublishConnectionInfo() + public SqlDockerSetup() { - ConnectionString = $"Server=127.0.0.1,{ExternalPort};Database=workflowcore-tests;User Id=sa;Password={SqlPassword};"; - ScenarioConnectionString = $"Server=127.0.0.1,{ExternalPort};Database=workflowcore-scenario-tests;User Id=sa;Password={SqlPassword};"; + _sqlServerResource = new SqlServerResource(); } - public override bool TestReady() + public async Task InitializeAsync() { - try - { - var client = new SqlConnection($"Server=127.0.0.1,{ExternalPort};Database=master;User Id=sa;Password={SqlPassword};"); - client.Open(); - client.Close(); - return true; - } - catch - { - return false; - } + await _sqlServerResource.InitializeAsync(); + ConnectionString = _sqlServerResource.CreateConnectionString("workflowcore-tests"); + ScenarioConnectionString = _sqlServerResource.CreateConnectionString("workflowcore-scenario-tests"); + } + public Task DisposeAsync() + { + return _sqlServerResource.DisposeAsync(); } } @@ -46,5 +33,4 @@ public override bool TestReady() public class SqlServerCollection : ICollectionFixture { } - } \ No newline at end of file diff --git a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj index 36ee2a15d..aa93036ed 100644 --- a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj +++ b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj @@ -2,8 +2,9 @@ - - + + + From dac4917c7ddb5871d1653f3edbf85638dd6a5cf6 Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 22 Nov 2022 15:30:27 +0100 Subject: [PATCH 235/342] Switch elasticsearch tests --- .../ElasticsearchDockerSetup.cs | 39 +++++++------------ .../WorkflowCore.Tests.Elasticsearch.csproj | 5 ++- 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs b/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs index 4bb1c57f9..6690c2732 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs +++ b/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs @@ -1,42 +1,29 @@ using System; -using System.Collections.Generic; -using Docker.Testify; -using Nest; +using System.Threading.Tasks; +using Squadron; using Xunit; namespace WorkflowCore.Tests.Elasticsearch { - public class ElasticsearchDockerSetup : DockerSetup + public class ElasticsearchDockerSetup : IAsyncLifetime { + private readonly ElasticsearchResource _elasticsearchResource; public static string ConnectionString { get; set; } - - public override string ImageName => @"elasticsearch"; - public override string ImageTag => "7.5.1"; - public override int InternalPort => 9200; - public override TimeSpan TimeOut => TimeSpan.FromSeconds(30); - - public override IList EnvironmentVariables => new List { - $"discovery.type=single-node" - }; - public override void PublishConnectionInfo() + public ElasticsearchDockerSetup() { - ConnectionString = $"http://localhost:{ExternalPort}"; + _elasticsearchResource = new ElasticsearchResource(); } - public override bool TestReady() + public async Task InitializeAsync() { - try - { - var client = new ElasticClient(new ConnectionSettings(new Uri($"http://localhost:{ExternalPort}"))); - var ping = client.Ping(); - return ping.IsValid; - } - catch - { - return false; - } + await _elasticsearchResource.InitializeAsync(); + ConnectionString = $"http://localhost:{_elasticsearchResource.Instance.HostPort}"; + } + public Task DisposeAsync() + { + return _elasticsearchResource.DisposeAsync(); } } diff --git a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj index 887e2df63..3050549bd 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj +++ b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj @@ -3,8 +3,9 @@ - - + + + From e77013106ca5b41ac6c6f841dc4b835efc3a5daa Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 22 Nov 2022 15:41:06 +0100 Subject: [PATCH 236/342] Consolidate tests projects dependencies --- test/Directory.Build.props | 21 ++++++++ .../WorkflowCore.IntegrationTests.csproj | 8 ---- .../WorkflowCore.TestAssets.csproj | 2 - .../WorkflowCore.Tests.DynamoDB.csproj | 3 -- .../WorkflowCore.Tests.Elasticsearch.csproj | 3 -- .../WorkflowCore.Tests.MongoDB.csproj | 6 --- test/WorkflowCore.Tests.MySQL/DockerSetup.cs | 48 +++++++------------ .../WorkflowCore.Tests.MySQL.csproj | 4 +- .../WorkflowCore.Tests.PostgreSQL.csproj | 3 -- ...wCore.Tests.QueueProviders.RabbitMQ.csproj | 4 -- .../WorkflowCore.Tests.Redis.csproj | 3 -- .../WorkflowCore.Tests.SqlServer.csproj | 3 -- .../WorkflowCore.Tests.Sqlite.csproj | 6 --- .../WorkflowCore.UnitTests.csproj | 11 ----- 14 files changed, 38 insertions(+), 87 deletions(-) diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 0f8bd594d..4d9ba3103 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -4,4 +4,25 @@ latest false + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj index 39390c2e6..bdc973728 100644 --- a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj +++ b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj @@ -18,14 +18,6 @@ - - - - - - - - diff --git a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj index 4530229d1..cbba0dccb 100644 --- a/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj +++ b/test/WorkflowCore.TestAssets/WorkflowCore.TestAssets.csproj @@ -38,8 +38,6 @@ - - diff --git a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj index 85593c9bb..65320489d 100644 --- a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj +++ b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj @@ -2,9 +2,6 @@ - - - diff --git a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj index 3050549bd..8702a25da 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj +++ b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj @@ -1,10 +1,7 @@  - - - diff --git a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj index 048f3d994..68251d271 100644 --- a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj +++ b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj @@ -20,13 +20,7 @@ - - - - - - diff --git a/test/WorkflowCore.Tests.MySQL/DockerSetup.cs b/test/WorkflowCore.Tests.MySQL/DockerSetup.cs index 05758f4c1..8a33f50fd 100644 --- a/test/WorkflowCore.Tests.MySQL/DockerSetup.cs +++ b/test/WorkflowCore.Tests.MySQL/DockerSetup.cs @@ -1,46 +1,31 @@ -using System.Collections.Generic; -using Docker.Testify; -using Xunit; +using Xunit; using System; -using MySqlConnector; +using System.Threading.Tasks; +using Squadron; namespace WorkflowCore.Tests.MySQL { - public class MysqlDockerSetup : DockerSetup + public class MysqlDockerSetup : IAsyncLifetime { + private readonly MySqlResource _mySqlResource; public static string ConnectionString { get; set; } public static string ScenarioConnectionString { get; set; } - public static string RootPassword => "rootpwd123"; - public override TimeSpan TimeOut => TimeSpan.FromSeconds(60); - - public override string ImageName => "mysql"; - public override IList EnvironmentVariables => new List { - $"MYSQL_ROOT_PASSWORD={RootPassword}" - }; - - public override int InternalPort => 3306; - - public override void PublishConnectionInfo() + public MysqlDockerSetup() { - ConnectionString = $"Server=127.0.0.1;Port={ExternalPort};Database=workflow;User=root;Password={RootPassword};"; - ScenarioConnectionString = $"Server=127.0.0.1;Port={ExternalPort};Database=scenarios;User=root;Password={RootPassword};"; + _mySqlResource = new MySqlResource(); } - - public override bool TestReady() + + public async Task InitializeAsync() { - try - { - var connection = new MySqlConnection($"host=127.0.0.1;port={ExternalPort};user=root;password={RootPassword};database=mysql;"); - connection.Open(); - connection.Close(); - return true; - } - catch - { - return false; - } + await _mySqlResource.InitializeAsync(); + ConnectionString = _mySqlResource.ConnectionString; + ScenarioConnectionString = _mySqlResource.ConnectionString; + } + public Task DisposeAsync() + { + return _mySqlResource.DisposeAsync(); } } @@ -48,5 +33,4 @@ public override bool TestReady() public class MysqlCollection : ICollectionFixture { } - } diff --git a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj index 1432348e2..cfdb4163d 100644 --- a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj +++ b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj @@ -1,9 +1,7 @@ - - - + diff --git a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj index a228ea763..66cc649b4 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj +++ b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj @@ -20,9 +20,6 @@ - - - diff --git a/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj b/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj index 0173d76bd..98e658fed 100644 --- a/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj +++ b/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj @@ -1,10 +1,6 @@ - - - - diff --git a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj index ddb796d70..147dad6da 100644 --- a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj +++ b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj @@ -1,10 +1,7 @@ - - - diff --git a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj index aa93036ed..24e83536e 100644 --- a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj +++ b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj @@ -1,9 +1,6 @@  - - - diff --git a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj index 31f839cf3..63acee283 100644 --- a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj +++ b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj @@ -1,11 +1,5 @@  - - - - - - diff --git a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj index f6ae01fbf..3ca6d6038 100644 --- a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj +++ b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj @@ -15,17 +15,6 @@ - - - - - - - - - - - From ef9b176c10af472e83530834d7653f5d84e7fcd0 Mon Sep 17 00:00:00 2001 From: glucaci Date: Tue, 22 Nov 2022 15:54:32 +0100 Subject: [PATCH 237/342] Fix dependencies --- test/Directory.Build.props | 8 ++------ test/ScratchPad/ScratchPad.csproj | 1 + .../WorkflowCore.Tests.Elasticsearch.csproj | 1 - 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 4d9ba3103..3b2ad7341 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -9,20 +9,16 @@ - + - - - + - - \ No newline at end of file diff --git a/test/ScratchPad/ScratchPad.csproj b/test/ScratchPad/ScratchPad.csproj index fdd4f1a3d..a194035c2 100644 --- a/test/ScratchPad/ScratchPad.csproj +++ b/test/ScratchPad/ScratchPad.csproj @@ -7,6 +7,7 @@ false false false + false diff --git a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj index 8702a25da..9aa005f40 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj +++ b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj @@ -1,7 +1,6 @@  - From c37d4bbd9f9b7efbae6795f09151b88917f5fe76 Mon Sep 17 00:00:00 2001 From: glucaci Date: Thu, 24 Nov 2022 08:47:42 +0100 Subject: [PATCH 238/342] Isolate MongoDB tests --- .../MongoPersistenceProviderFixture.cs | 2 +- .../Scenarios/MongoActivityScenario.cs | 2 +- test/WorkflowCore.Tests.MongoDB/Scenarios/MongoBasicScenario.cs | 2 +- .../Scenarios/MongoCompensationScenario.cs | 2 +- test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDataScenario.cs | 2 +- .../Scenarios/MongoDecisionScenario.cs | 2 +- test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDelayScenario.cs | 2 +- test/WorkflowCore.Tests.MongoDB/Scenarios/MongoEventScenario.cs | 2 +- .../Scenarios/MongoForEachScenario.cs | 2 +- test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForkScenario.cs | 2 +- test/WorkflowCore.Tests.MongoDB/Scenarios/MongoIfScenario.cs | 2 +- .../Scenarios/MongoRetrySagaScenario.cs | 2 +- test/WorkflowCore.Tests.MongoDB/Scenarios/MongoSagaScenario.cs | 2 +- test/WorkflowCore.Tests.MongoDB/Scenarios/MongoUserScenario.cs | 2 +- test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhenScenario.cs | 2 +- test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhileScenario.cs | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/test/WorkflowCore.Tests.MongoDB/MongoPersistenceProviderFixture.cs b/test/WorkflowCore.Tests.MongoDB/MongoPersistenceProviderFixture.cs index 79de07a97..c61b4b5e2 100644 --- a/test/WorkflowCore.Tests.MongoDB/MongoPersistenceProviderFixture.cs +++ b/test/WorkflowCore.Tests.MongoDB/MongoPersistenceProviderFixture.cs @@ -22,7 +22,7 @@ protected override IPersistenceProvider Subject get { var client = new MongoClient(MongoDockerSetup.ConnectionString); - var db = client.GetDatabase("workflow-tests"); + var db = client.GetDatabase(nameof(MongoPersistenceProviderFixture)); return new MongoPersistenceProvider(db); } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoActivityScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoActivityScenario.cs index 52625678f..ca815f41a 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoActivityScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoActivityScenario.cs @@ -14,7 +14,7 @@ protected override void ConfigureServices(IServiceCollection services) BsonClassMap.RegisterClassMap(x => x.AutoMap()); BsonClassMap.RegisterClassMap(x => x.AutoMap()); - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); + services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoActivityScenario))); } } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoBasicScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoBasicScenario.cs index bec7c6d50..c24ffe46c 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoBasicScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoBasicScenario.cs @@ -10,7 +10,7 @@ public class MongoBasicScenario : BasicScenario { protected override void ConfigureServices(IServiceCollection services) { - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); + services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoBasicScenario))); } } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoCompensationScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoCompensationScenario.cs index 8adf4b4bd..ed3114e55 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoCompensationScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoCompensationScenario.cs @@ -10,7 +10,7 @@ public class MongoCompensationScenario : CompensationScenario { protected override void ConfigureServices(IServiceCollection services) { - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); + services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoCompensationScenario))); } } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDataScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDataScenario.cs index e842f6fee..6c647bebd 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDataScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDataScenario.cs @@ -16,7 +16,7 @@ public MongoDataScenario() : base() protected override void ConfigureServices(IServiceCollection services) { - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); + services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoDataScenario))); } } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDecisionScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDecisionScenario.cs index b5f8fd01f..0db093806 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDecisionScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDecisionScenario.cs @@ -10,7 +10,7 @@ public class MongoDecisionScenario : DecisionScenario { protected override void ConfigureServices(IServiceCollection services) { - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); + services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoDecisionScenario))); } } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDelayScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDelayScenario.cs index 511aa79fb..45aca549f 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDelayScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoDelayScenario.cs @@ -18,7 +18,7 @@ protected override void ConfigureServices(IServiceCollection services) { services.AddWorkflow(cfg => { - cfg.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests"); + cfg.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoDelayScenario)); cfg.UsePollInterval(TimeSpan.FromSeconds(2)); }); } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoEventScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoEventScenario.cs index b789bab5b..2aa6e8461 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoEventScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoEventScenario.cs @@ -10,7 +10,7 @@ public class MongoEventScenario : EventScenario { protected override void ConfigureServices(IServiceCollection services) { - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); + services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoEventScenario))); } } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForEachScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForEachScenario.cs index c8b718753..5fa8b94b8 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForEachScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForEachScenario.cs @@ -10,7 +10,7 @@ public class MongoForEachScenario : ForeachScenario { protected override void ConfigureServices(IServiceCollection services) { - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); + services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoForEachScenario))); } } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForkScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForkScenario.cs index 319af0466..f582f0e7b 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForkScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoForkScenario.cs @@ -10,7 +10,7 @@ public class MongoForkScenario : ForkScenario { protected override void Configure(IServiceCollection services) { - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); + services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoForkScenario))); } } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoIfScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoIfScenario.cs index 7ea42fd98..5c78d3ddc 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoIfScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoIfScenario.cs @@ -10,7 +10,7 @@ public class MongoIfScenario : IfScenario { protected override void ConfigureServices(IServiceCollection services) { - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); + services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoIfScenario))); } } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoRetrySagaScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoRetrySagaScenario.cs index b8a9ec92b..5e30ed877 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoRetrySagaScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoRetrySagaScenario.cs @@ -10,7 +10,7 @@ public class MongoRetrySagaScenario : RetrySagaScenario { protected override void ConfigureServices(IServiceCollection services) { - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); + services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoRetrySagaScenario))); } } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoSagaScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoSagaScenario.cs index e5d666a9c..c9ceb9d83 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoSagaScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoSagaScenario.cs @@ -10,7 +10,7 @@ public class MongoSagaScenario : SagaScenario { protected override void ConfigureServices(IServiceCollection services) { - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); + services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoSagaScenario))); } } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoUserScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoUserScenario.cs index 93ec848ee..fbaa0f223 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoUserScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoUserScenario.cs @@ -10,7 +10,7 @@ public class MongoUserScenario : UserScenario { protected override void ConfigureServices(IServiceCollection services) { - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); + services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoUserScenario))); } } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhenScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhenScenario.cs index 6cca92b6b..b966f35b8 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhenScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhenScenario.cs @@ -10,7 +10,7 @@ public class MongoWhenScenario : WhenScenario { protected override void ConfigureServices(IServiceCollection services) { - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); + services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoWhenScenario))); } } } diff --git a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhileScenario.cs b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhileScenario.cs index 4c7aaead9..78e5277f6 100644 --- a/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhileScenario.cs +++ b/test/WorkflowCore.Tests.MongoDB/Scenarios/MongoWhileScenario.cs @@ -10,7 +10,7 @@ public class MongoWhileScenario : WhileScenario { protected override void ConfigureServices(IServiceCollection services) { - services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, "integration-tests")); + services.AddWorkflow(x => x.UseMongoDB(MongoDockerSetup.ConnectionString, nameof(MongoWhileScenario))); } } } From c955bc8dff328d9eb7079f2626ba9fbb63fb7e65 Mon Sep 17 00:00:00 2001 From: glucaci Date: Thu, 24 Nov 2022 08:59:37 +0100 Subject: [PATCH 239/342] Fix postgres tests --- test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs b/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs index 3f7739ee9..1e628713f 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs @@ -13,6 +13,7 @@ public class PostgresDockerSetup : IAsyncLifetime public PostgresDockerSetup() { + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); _postgreSqlResource = new PostgreSqlResource(); } From fde25bf1019851ad61dedfb6cd37279750875f8a Mon Sep 17 00:00:00 2001 From: glucaci Date: Thu, 24 Nov 2022 09:32:26 +0100 Subject: [PATCH 240/342] Cleanup --- .../ElasticsearchDockerSetup.cs | 2 +- test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs | 8 ++++---- test/WorkflowCore.Tests.MySQL/DockerSetup.cs | 4 ++-- test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs | 8 ++++---- test/WorkflowCore.Tests.Redis/RedisDockerSetup.cs | 6 +++--- test/WorkflowCore.Tests.SqlServer/DockerSetup.cs | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs b/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs index 6690c2732..4ed16a152 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs +++ b/test/WorkflowCore.Tests.Elasticsearch/ElasticsearchDockerSetup.cs @@ -31,4 +31,4 @@ public Task DisposeAsync() public class ElasticsearchCollection : ICollectionFixture { } -} +} \ No newline at end of file diff --git a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs index 139fef30f..7b956196d 100644 --- a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs +++ b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs @@ -5,7 +5,7 @@ using Xunit; namespace WorkflowCore.Tests.MongoDB -{ +{ public class MongoDockerSetup : IAsyncLifetime { private readonly MongoResource _mongoResource; @@ -15,7 +15,7 @@ public MongoDockerSetup() { _mongoResource = new MongoResource(); } - + public async Task InitializeAsync() { await _mongoResource.InitializeAsync(); @@ -33,6 +33,6 @@ public Task DisposeAsync() [CollectionDefinition("Mongo collection")] public class MongoCollection : ICollectionFixture - { + { } -} +} \ No newline at end of file diff --git a/test/WorkflowCore.Tests.MySQL/DockerSetup.cs b/test/WorkflowCore.Tests.MySQL/DockerSetup.cs index 8a33f50fd..9444a8005 100644 --- a/test/WorkflowCore.Tests.MySQL/DockerSetup.cs +++ b/test/WorkflowCore.Tests.MySQL/DockerSetup.cs @@ -15,7 +15,7 @@ public MysqlDockerSetup() { _mySqlResource = new MySqlResource(); } - + public async Task InitializeAsync() { await _mySqlResource.InitializeAsync(); @@ -33,4 +33,4 @@ public Task DisposeAsync() public class MysqlCollection : ICollectionFixture { } -} +} \ No newline at end of file diff --git a/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs b/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs index 1e628713f..8548bf85d 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs +++ b/test/WorkflowCore.Tests.PostgreSQL/DockerSetup.cs @@ -16,7 +16,7 @@ public PostgresDockerSetup() AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); _postgreSqlResource = new PostgreSqlResource(); } - + public async Task InitializeAsync() { await _postgreSqlResource.InitializeAsync(); @@ -29,9 +29,9 @@ public Task DisposeAsync() return _postgreSqlResource.DisposeAsync(); } } - + [CollectionDefinition("Postgres collection")] public class PostgresCollection : ICollectionFixture - { + { } -} +} \ No newline at end of file diff --git a/test/WorkflowCore.Tests.Redis/RedisDockerSetup.cs b/test/WorkflowCore.Tests.Redis/RedisDockerSetup.cs index 0cc13c8b2..4faba0af2 100644 --- a/test/WorkflowCore.Tests.Redis/RedisDockerSetup.cs +++ b/test/WorkflowCore.Tests.Redis/RedisDockerSetup.cs @@ -4,7 +4,7 @@ using Xunit; namespace WorkflowCore.Tests.Redis -{ +{ public class RedisDockerSetup : IAsyncLifetime { private readonly RedisResource _redisResource; @@ -29,6 +29,6 @@ public Task DisposeAsync() [CollectionDefinition("Redis collection")] public class RedisCollection : ICollectionFixture - { + { } -} +} \ No newline at end of file diff --git a/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs b/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs index 147c09241..cf50f854d 100644 --- a/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs +++ b/test/WorkflowCore.Tests.SqlServer/DockerSetup.cs @@ -31,6 +31,6 @@ public Task DisposeAsync() [CollectionDefinition("SqlServer collection")] public class SqlServerCollection : ICollectionFixture - { + { } } \ No newline at end of file From 286b9fef42a419347b0d38ee407f798782ca8f67 Mon Sep 17 00:00:00 2001 From: glucaci Date: Fri, 25 Nov 2022 11:51:12 +0100 Subject: [PATCH 241/342] Enable no table scan and fix one more index --- .../Services/MongoPersistenceProvider.cs | 6 ++++-- test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs | 5 ++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index 0d238ec64..551167add 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -112,8 +112,10 @@ static void CreateIndexes(MongoPersistenceProvider instance) instance.EventSubscriptions.Indexes.CreateOne(new CreateIndexModel( Builders.IndexKeys .Ascending(x => x.EventName) - .Ascending(x => x.EventKey), - new CreateIndexOptions { Background = true, Name = "idx_namekey" })); + .Ascending(x => x.EventKey) + .Ascending(x => x.SubscribeAsOf) + .Ascending(x => x.ExternalToken), + new CreateIndexOptions { Background = true, Name = "idx_namekey_v2" })); instance.ScheduledCommands.Indexes.CreateOne(new CreateIndexModel( Builders.IndexKeys diff --git a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs index 7b956196d..fddf108c6 100644 --- a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs +++ b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs @@ -19,9 +19,8 @@ public MongoDockerSetup() public async Task InitializeAsync() { await _mongoResource.InitializeAsync(); - // TODO: Should be enabled - // var command = new BsonDocument { { "setParameter", 1 }, { "notablescan", 1 } }; - // _mongoResource.Client.GetDatabase("admin").RunCommand(command); + var command = new BsonDocument { { "setParameter", 1 }, { "notablescan", 1 } }; + _mongoResource.Client.GetDatabase("admin").RunCommand(command); ConnectionString = _mongoResource.ConnectionString; } From 5ae4acb2976cb16e3967edde9cc63b00a2bd2cfa Mon Sep 17 00:00:00 2001 From: glucaci Date: Fri, 25 Nov 2022 12:16:43 +0100 Subject: [PATCH 242/342] Try fix index --- .../Services/MongoPersistenceProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index 551167add..034e4e402 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -111,8 +111,8 @@ static void CreateIndexes(MongoPersistenceProvider instance) instance.EventSubscriptions.Indexes.CreateOne(new CreateIndexModel( Builders.IndexKeys - .Ascending(x => x.EventName) .Ascending(x => x.EventKey) + .Ascending(x => x.EventName) .Ascending(x => x.SubscribeAsOf) .Ascending(x => x.ExternalToken), new CreateIndexOptions { Background = true, Name = "idx_namekey_v2" })); From ae94ecb82a5961c2e3af14f98b71139fb84021e8 Mon Sep 17 00:00:00 2001 From: glucaci Date: Fri, 25 Nov 2022 15:15:48 +0100 Subject: [PATCH 243/342] Fix index --- .../Services/MongoPersistenceProvider.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index 034e4e402..0f9fca3cf 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -112,10 +112,16 @@ static void CreateIndexes(MongoPersistenceProvider instance) instance.EventSubscriptions.Indexes.CreateOne(new CreateIndexModel( Builders.IndexKeys .Ascending(x => x.EventKey) - .Ascending(x => x.EventName) - .Ascending(x => x.SubscribeAsOf) - .Ascending(x => x.ExternalToken), + .Ascending(x => x.EventName), new CreateIndexOptions { Background = true, Name = "idx_namekey_v2" })); + + instance.EventSubscriptions.Indexes.CreateOne(new CreateIndexModel( + Builders.IndexKeys.Ascending(x => x.SubscribeAsOf), + new CreateIndexOptions { Background = true, Name = "idx_subscribe" })); + + instance.EventSubscriptions.Indexes.CreateOne(new CreateIndexModel( + Builders.IndexKeys.Ascending(x => x.ExternalToken), + new CreateIndexOptions { Background = true, Name = "idx_token" })); instance.ScheduledCommands.Indexes.CreateOne(new CreateIndexModel( Builders.IndexKeys From 53143d410ac08e503db7962dc876482e23f69f30 Mon Sep 17 00:00:00 2001 From: glucaci Date: Sat, 26 Nov 2022 09:58:40 +0100 Subject: [PATCH 244/342] Complete index --- .../Services/MongoPersistenceProvider.cs | 17 +++++------------ .../MongoDockerSetup.cs | 2 -- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index 0f9fca3cf..fe43589b6 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -95,7 +95,8 @@ static void CreateIndexes(MongoPersistenceProvider instance) instance.WorkflowInstances.Indexes.CreateOne(new CreateIndexModel( Builders.IndexKeys .Ascending(x => x.NextExecution) - .Ascending(x => x.Status), + .Ascending(x => x.Status) + .Ascending(x => x.Id), new CreateIndexOptions {Background = true, Name = "idx_nextExec_v2"})); instance.Events.Indexes.CreateOne(new CreateIndexModel( @@ -111,17 +112,9 @@ static void CreateIndexes(MongoPersistenceProvider instance) instance.EventSubscriptions.Indexes.CreateOne(new CreateIndexModel( Builders.IndexKeys - .Ascending(x => x.EventKey) - .Ascending(x => x.EventName), - new CreateIndexOptions { Background = true, Name = "idx_namekey_v2" })); - - instance.EventSubscriptions.Indexes.CreateOne(new CreateIndexModel( - Builders.IndexKeys.Ascending(x => x.SubscribeAsOf), - new CreateIndexOptions { Background = true, Name = "idx_subscribe" })); - - instance.EventSubscriptions.Indexes.CreateOne(new CreateIndexModel( - Builders.IndexKeys.Ascending(x => x.ExternalToken), - new CreateIndexOptions { Background = true, Name = "idx_token" })); + .Ascending(x => x.EventName) + .Ascending(x => x.EventKey), + new CreateIndexOptions { Background = true, Name = "idx_namekey" })); instance.ScheduledCommands.Indexes.CreateOne(new CreateIndexModel( Builders.IndexKeys diff --git a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs index fddf108c6..df281ce29 100644 --- a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs +++ b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs @@ -19,8 +19,6 @@ public MongoDockerSetup() public async Task InitializeAsync() { await _mongoResource.InitializeAsync(); - var command = new BsonDocument { { "setParameter", 1 }, { "notablescan", 1 } }; - _mongoResource.Client.GetDatabase("admin").RunCommand(command); ConnectionString = _mongoResource.ConnectionString; } From e00d53bb4d4cb144bd484fd894e81e93bf1b4116 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sun, 27 Nov 2022 17:42:21 -0800 Subject: [PATCH 245/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 298e3079c..a56e32d2d 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.7.0 - 3.7.0.0 - 3.7.0.0 + 3.8.0 + 3.8.0.0 + 3.8.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.7.0 + 3.8.0 From 8fce34fa216d2630758eb34891b4f37c1e399ab3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Nov 2022 01:53:51 +0000 Subject: [PATCH 246/342] Bump System.Data.SqlClient Bumps [System.Data.SqlClient](https://github.com/dotnet/corefx) from 4.6.1 to 4.8.5. - [Release notes](https://github.com/dotnet/corefx/releases) - [Commits](https://github.com/dotnet/corefx/commits) --- updated-dependencies: - dependency-name: System.Data.SqlClient dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .../WorkflowCore.QueueProviders.SqlServer.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj index 77d5e2421..c24b7d89e 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj @@ -22,7 +22,7 @@ - + From 5edfa3087062bdc48f24da8640dc7bc23418feb1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Nov 2022 01:54:11 +0000 Subject: [PATCH 247/342] Bump System.Data.SqlClient Bumps [System.Data.SqlClient](https://github.com/dotnet/corefx) from 4.6.1 to 4.8.5. - [Release notes](https://github.com/dotnet/corefx/releases) - [Commits](https://github.com/dotnet/corefx/commits) --- updated-dependencies: - dependency-name: System.Data.SqlClient dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .../WorkflowCore.LockProviders.SqlServer.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj b/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj index 77fbe950d..5c798129a 100644 --- a/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj @@ -8,7 +8,7 @@ - + From 2fe3916859a14b0b4d9cdbbd6e0a8681d32812b1 Mon Sep 17 00:00:00 2001 From: glucaci Date: Mon, 28 Nov 2022 08:54:36 +0100 Subject: [PATCH 248/342] Add mysql to PR build --- .github/workflows/dotnet.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 8bb2947f6..83afb451b 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -55,6 +55,22 @@ jobs: run: dotnet build --no-restore - name: MongoDB Tests run: dotnet test test/WorkflowCore.Tests.MongoDB --no-build --verbosity normal -p:ParallelizeTestCollections=false + MySQL-Tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: | + 3.1.x + 6.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: MySQL Tests + run: dotnet test test/WorkflowCore.Tests.MySQL --no-build --verbosity normal -p:ParallelizeTestCollections=false PostgreSQL-Tests: runs-on: ubuntu-latest steps: From 136238445ca1c7f61aabeb9715092b5acb94faf9 Mon Sep 17 00:00:00 2001 From: glucaci Date: Mon, 28 Nov 2022 11:52:54 +0100 Subject: [PATCH 249/342] Fix mysql tests --- test/WorkflowCore.Tests.MySQL/DockerSetup.cs | 8 +++++--- .../WorkflowCore.Tests.MySQL.csproj | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/test/WorkflowCore.Tests.MySQL/DockerSetup.cs b/test/WorkflowCore.Tests.MySQL/DockerSetup.cs index 9444a8005..06c041818 100644 --- a/test/WorkflowCore.Tests.MySQL/DockerSetup.cs +++ b/test/WorkflowCore.Tests.MySQL/DockerSetup.cs @@ -19,8 +19,10 @@ public MysqlDockerSetup() public async Task InitializeAsync() { await _mySqlResource.InitializeAsync(); - ConnectionString = _mySqlResource.ConnectionString; - ScenarioConnectionString = _mySqlResource.ConnectionString; + var workflowConnection = await _mySqlResource.CreateDatabaseAsync("workflow"); + ConnectionString = workflowConnection.ConnectionString; + var scenariosConnection = await _mySqlResource.CreateDatabaseAsync("scenarios"); + ScenarioConnectionString = scenariosConnection.ConnectionString; } public Task DisposeAsync() @@ -28,7 +30,7 @@ public Task DisposeAsync() return _mySqlResource.DisposeAsync(); } } - + [CollectionDefinition("Mysql collection")] public class MysqlCollection : ICollectionFixture { diff --git a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj index cfdb4163d..a56acc9b7 100644 --- a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj +++ b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj @@ -1,7 +1,7 @@ - + From 6a7ae386b1e200ad638b0db026a3bc614d4f2995 Mon Sep 17 00:00:00 2001 From: glucaci Date: Wed, 7 Dec 2022 14:54:07 +0100 Subject: [PATCH 250/342] Fix persist workflow when has no subscription --- .../Services/BackgroundTasks/WorkflowConsumer.cs | 2 +- .../Services/MongoPersistenceProvider.cs | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index 3a6465902..b092f41f6 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -55,7 +55,7 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance finally { WorkflowActivity.Enrich(result); - await _persistenceStore.PersistWorkflow(workflow, result.Subscriptions, cancellationToken); + await _persistenceStore.PersistWorkflow(workflow, result?.Subscriptions, cancellationToken); await QueueProvider.QueueWork(itemId, QueueType.Index); _greylist.Remove($"wf:{itemId}"); } diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index fe43589b6..fdab92cf6 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -154,12 +154,18 @@ public async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken c public async Task PersistWorkflow(WorkflowInstance workflow, List subscriptions, CancellationToken cancellationToken = default) { - using (var session = await _database.Client.StartSessionAsync()) + if (subscriptions == null || subscriptions.Count < 1) + { + await PersistWorkflow(workflow, cancellationToken); + return; + } + + using (var session = await _database.Client.StartSessionAsync(cancellationToken: cancellationToken)) { session.StartTransaction(); await PersistWorkflow(workflow, cancellationToken); await EventSubscriptions.InsertManyAsync(subscriptions, cancellationToken: cancellationToken); - await session.CommitTransactionAsync(); + await session.CommitTransactionAsync(cancellationToken); } } From 86ed4fad656286568417f0cf3e82fc1a4be1aa3f Mon Sep 17 00:00:00 2001 From: glucaci Date: Wed, 7 Dec 2022 14:59:04 +0100 Subject: [PATCH 251/342] Update version --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index a56e32d2d..8793e7e27 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.8.0 - 3.8.0.0 - 3.8.0.0 + 3.8.1 + 3.8.1.0 + 3.8.1.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.8.0 + 3.8.1 From a9a4e5c59c976ce6dbfc3295b73e1b3f1ade957f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Dec 2022 22:11:10 +0000 Subject: [PATCH 252/342] Bump Newtonsoft.Json in /src/samples/WebApiSample/WebApiSample Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 13.0.1 to 13.0.2. - [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases) - [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/13.0.1...13.0.2) --- updated-dependencies: - dependency-name: Newtonsoft.Json dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- src/samples/WebApiSample/WebApiSample/WebApiSample.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/samples/WebApiSample/WebApiSample/WebApiSample.csproj b/src/samples/WebApiSample/WebApiSample/WebApiSample.csproj index 133f705b4..e1454eb7d 100644 --- a/src/samples/WebApiSample/WebApiSample/WebApiSample.csproj +++ b/src/samples/WebApiSample/WebApiSample/WebApiSample.csproj @@ -14,7 +14,7 @@ - + From b5e141f4b798ddcd85cc3a0495d57e6dbfe4b796 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Mar 2023 23:26:00 +0000 Subject: [PATCH 253/342] Bump MongoDB.Driver in /test/WorkflowCore.Tests.MongoDB Bumps [MongoDB.Driver](https://github.com/mongodb/mongo-csharp-driver) from 2.8.1 to 2.19.0. - [Release notes](https://github.com/mongodb/mongo-csharp-driver/releases) - [Commits](https://github.com/mongodb/mongo-csharp-driver/compare/v2.8.1...v2.19.0) --- updated-dependencies: - dependency-name: MongoDB.Driver dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .../WorkflowCore.Persistence.MongoDB.csproj | 2 +- .../WorkflowCore.Tests.MongoDB.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj index 5d395eee9..e55685a2e 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj +++ b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj @@ -22,7 +22,7 @@ - + diff --git a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj index 68251d271..c708f7bf3 100644 --- a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj +++ b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj @@ -21,7 +21,7 @@ - + From 2cc7b6723e18bbb1403f04ad9765bf05ab9fac18 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 Mar 2023 01:11:54 +0000 Subject: [PATCH 254/342] Bump MongoDB.Driver in /src/providers/WorkflowCore.Persistence.MongoDB Bumps [MongoDB.Driver](https://github.com/mongodb/mongo-csharp-driver) from 2.8.1 to 2.19.0. - [Release notes](https://github.com/mongodb/mongo-csharp-driver/releases) - [Commits](https://github.com/mongodb/mongo-csharp-driver/compare/v2.8.1...v2.19.0) --- updated-dependencies: - dependency-name: MongoDB.Driver dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .../WorkflowCore.Persistence.MongoDB.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj index 5d395eee9..e55685a2e 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj +++ b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj @@ -22,7 +22,7 @@ - + From 452b15fce725b5205bf65ca9bb82c31db9a9e2e7 Mon Sep 17 00:00:00 2001 From: Christian Jundt Date: Fri, 10 Mar 2023 16:30:57 +0100 Subject: [PATCH 255/342] oracle persistance provides + unit tests --- WorkflowCore.sln | 18 +- .../MigrationContextFactory.cs | 15 + ...20230310125506_InitialDatabase.Designer.cs | 377 ++++++++++++++++++ .../20230310125506_InitialDatabase.cs | 260 ++++++++++++ .../Migrations/OracleContextModelSnapshot.cs | 375 +++++++++++++++++ .../OracleContext.cs | 74 ++++ .../OracleContextFactory.cs | 29 ++ .../WorkflowCore.Persistence.Oracle/README.md | 19 + .../ServiceCollectionExtensions.cs | 24 ++ .../WorkflowCore.Persistence.Oracle.csproj | 43 ++ .../Scenarios/ActivityScenario.cs | 2 +- .../OraclePersistenceProviderFixture.cs | 25 ++ test/WorkflowCore.Tests.Oracle/OracleSetup.cs | 26 ++ .../Properties/AssemblyInfo.cs | 18 + .../Scenarios/OracleActivityScenario.cs | 19 + .../Scenarios/OracleBasicScenario.cs | 19 + .../Scenarios/OracleDataScenario.cs | 19 + .../Scenarios/OracleDelayScenario.cs | 23 ++ .../Scenarios/OracleDynamicDataScenario.cs | 19 + .../Scenarios/OracleEventScenario.cs | 19 + .../Scenarios/OracleForeachScenario.cs | 19 + .../Scenarios/OracleForkScenario.cs | 19 + .../Scenarios/OracleIfScenario.cs | 19 + .../Scenarios/OracleRetrySagaScenario.cs | 19 + .../Scenarios/OracleSagaScenario.cs | 19 + .../Scenarios/OracleUserScenario.cs | 19 + .../Scenarios/OracleWhenScenario.cs | 19 + .../Scenarios/OracleWhileScenario.cs | 19 + .../WorkflowCore.Tests.Oracle.csproj | 21 + 29 files changed, 1593 insertions(+), 3 deletions(-) create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/MigrationContextFactory.cs create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.Designer.cs create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/OracleContext.cs create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/OracleContextFactory.cs create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/README.md create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/ServiceCollectionExtensions.cs create mode 100644 src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj create mode 100644 test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs create mode 100644 test/WorkflowCore.Tests.Oracle/OracleSetup.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Properties/AssemblyInfo.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleActivityScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleBasicScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleDataScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleDynamicDataScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleEventScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleForeachScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleForkScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleIfScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleRetrySagaScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleSagaScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleUserScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhenScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhileScenario.cs create mode 100644 test/WorkflowCore.Tests.Oracle/WorkflowCore.Tests.Oracle.csproj diff --git a/WorkflowCore.sln b/WorkflowCore.sln index e7fb81a2e..25c2016d2 100644 --- a/WorkflowCore.sln +++ b/WorkflowCore.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.5.33424.131 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EF47161E-E399-451C-BDE8-E92AAD3BD761}" EndProject @@ -154,6 +154,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Sample19", "sr EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Persistence.RavenDB", "src\providers\WorkflowCore.Persistence.RavenDB\WorkflowCore.Persistence.RavenDB.csproj", "{AF205715-C8B7-42EF-BF14-AFC9E7F27242}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Persistence.Oracle", "src\providers\WorkflowCore.Persistence.Oracle\WorkflowCore.Persistence.Oracle.csproj", "{635629BC-9D5C-40C6-BBD0-060550ECE290}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowCore.Tests.Oracle", "test\WorkflowCore.Tests.Oracle\WorkflowCore.Tests.Oracle.csproj", "{A2837F1C-3740-4375-9069-81AE32C867CA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -376,6 +380,14 @@ Global {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Debug|Any CPU.Build.0 = Debug|Any CPU {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Release|Any CPU.ActiveCfg = Release|Any CPU {AF205715-C8B7-42EF-BF14-AFC9E7F27242}.Release|Any CPU.Build.0 = Release|Any CPU + {635629BC-9D5C-40C6-BBD0-060550ECE290}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {635629BC-9D5C-40C6-BBD0-060550ECE290}.Debug|Any CPU.Build.0 = Debug|Any CPU + {635629BC-9D5C-40C6-BBD0-060550ECE290}.Release|Any CPU.ActiveCfg = Release|Any CPU + {635629BC-9D5C-40C6-BBD0-060550ECE290}.Release|Any CPU.Build.0 = Release|Any CPU + {A2837F1C-3740-4375-9069-81AE32C867CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2837F1C-3740-4375-9069-81AE32C867CA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A2837F1C-3740-4375-9069-81AE32C867CA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2837F1C-3740-4375-9069-81AE32C867CA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -438,6 +450,8 @@ Global {54DE20BA-EBA7-4BF0-9BD9-F03766849716} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} {1223ED47-3E5E-4960-B70D-DFAF550F6666} = {5080DB09-CBE8-4C45-9957-C3BB7651755E} {AF205715-C8B7-42EF-BF14-AFC9E7F27242} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} + {635629BC-9D5C-40C6-BBD0-060550ECE290} = {2EEE6ABD-EE9B-473F-AF2D-6DABB85D7BA2} + {A2837F1C-3740-4375-9069-81AE32C867CA} = {E6CEAD8D-F565-471E-A0DC-676F54EAEDEB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC0FA8D3-6449-4FDA-BB46-ECF58FAD23B4} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/MigrationContextFactory.cs b/src/providers/WorkflowCore.Persistence.Oracle/MigrationContextFactory.cs new file mode 100644 index 000000000..687109711 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/MigrationContextFactory.cs @@ -0,0 +1,15 @@ +using System; +using System.Linq; + +using Microsoft.EntityFrameworkCore.Design; + +namespace WorkflowCore.Persistence.Oracle +{ + public class MigrationContextFactory : IDesignTimeDbContextFactory + { + public OracleContext CreateDbContext(string[] args) + { + return new OracleContext(@"Server=127.0.0.1;Database=myDataBase;Uid=myUsername;Pwd=myPassword;"); + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.Designer.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.Designer.cs new file mode 100644 index 000000000..7948bc948 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.Designer.cs @@ -0,0 +1,377 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Oracle.EntityFrameworkCore.Metadata; +using WorkflowCore.Persistence.Oracle; + +#nullable disable + +namespace WorkflowCore.Persistence.Oracle.Migrations +{ + [DbContext(typeof(OracleContext))] + [Migration("20230310125506_InitialDatabase")] + partial class InitialDatabase + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("EventData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("EventId") + .HasColumnType("RAW(16)"); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("EventTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("IsProcessed") + .HasColumnType("NUMBER(1)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventId") + .IsUnique(); + + b.HasIndex("EventTime"); + + b.HasIndex("IsProcessed"); + + b.HasIndex("EventName", "EventKey"); + + b.ToTable("Event", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionError", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("ErrorTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("ExecutionPointerId") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("Message") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("WorkflowId") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.HasKey("PersistenceId"); + + b.ToTable("ExecutionError", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("Active") + .HasColumnType("NUMBER(1)"); + + b.Property("Children") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("ContextItem") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("EndTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("EventData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("EventKey") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("EventName") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("EventPublished") + .HasColumnType("NUMBER(1)"); + + b.Property("Id") + .HasMaxLength(50) + .HasColumnType("NVARCHAR2(50)"); + + b.Property("Outcome") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("PersistenceData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("PredecessorId") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("RetryCount") + .HasColumnType("NUMBER(10)"); + + b.Property("Scope") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("SleepUntil") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("StartTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("Status") + .HasColumnType("NUMBER(10)"); + + b.Property("StepId") + .HasColumnType("NUMBER(10)"); + + b.Property("StepName") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("WorkflowId") + .HasColumnType("NUMBER(19)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("WorkflowId"); + + b.ToTable("ExecutionPointer", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("AttributeKey") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("AttributeValue") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("ExecutionPointerId") + .HasColumnType("NUMBER(19)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecutionPointerId"); + + b.ToTable("ExtensionAttribute", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedScheduledCommand", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("CommandName") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("Data") + .HasMaxLength(500) + .HasColumnType("NVARCHAR2(500)"); + + b.Property("ExecuteTime") + .HasColumnType("NUMBER(19)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecuteTime"); + + b.HasIndex("CommandName", "Data") + .IsUnique() + .HasFilter("\"CommandName\" IS NOT NULL AND \"Data\" IS NOT NULL"); + + b.ToTable("ScheduledCommand", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("ExecutionPointerId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("ExternalToken") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("ExternalTokenExpiry") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("ExternalWorkerId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("StepId") + .HasColumnType("NUMBER(10)"); + + b.Property("SubscribeAsOf") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("SubscriptionData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("SubscriptionId") + .HasMaxLength(200) + .HasColumnType("RAW(16)"); + + b.Property("WorkflowId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventKey"); + + b.HasIndex("EventName"); + + b.HasIndex("SubscriptionId") + .IsUnique(); + + b.ToTable("Subscription", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("CompleteTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("CreateTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("Data") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("NVARCHAR2(500)"); + + b.Property("InstanceId") + .HasMaxLength(200) + .HasColumnType("RAW(16)"); + + b.Property("NextExecution") + .HasColumnType("NUMBER(19)"); + + b.Property("Reference") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("Status") + .HasColumnType("NUMBER(10)"); + + b.Property("Version") + .HasColumnType("NUMBER(10)"); + + b.Property("WorkflowDefinitionId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("InstanceId") + .IsUnique(); + + b.HasIndex("NextExecution"); + + b.ToTable("Workflow", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", "Workflow") + .WithMany("ExecutionPointers") + .HasForeignKey("WorkflowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Workflow"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", "ExecutionPointer") + .WithMany("ExtensionAttributes") + .HasForeignKey("ExecutionPointerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ExecutionPointer"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Navigation("ExtensionAttributes"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Navigation("ExecutionPointers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs new file mode 100644 index 000000000..9766e7c40 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs @@ -0,0 +1,260 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace WorkflowCore.Persistence.Oracle.Migrations +{ + public partial class InitialDatabase : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Event", + columns: table => new + { + PersistenceId = table.Column(type: "NUMBER(19)", nullable: false) + .Annotation("Oracle:Identity", "START WITH 1 INCREMENT BY 1"), + EventId = table.Column(type: "RAW(16)", nullable: false), + EventName = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + EventKey = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + EventData = table.Column(type: "NVARCHAR2(2000)", nullable: true), + EventTime = table.Column(type: "TIMESTAMP(7)", nullable: false), + IsProcessed = table.Column(type: "NUMBER(1)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Event", x => x.PersistenceId); + }); + + migrationBuilder.CreateTable( + name: "ExecutionError", + columns: table => new + { + PersistenceId = table.Column(type: "NUMBER(19)", nullable: false) + .Annotation("Oracle:Identity", "START WITH 1 INCREMENT BY 1"), + WorkflowId = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + ExecutionPointerId = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + ErrorTime = table.Column(type: "TIMESTAMP(7)", nullable: false), + Message = table.Column(type: "NVARCHAR2(2000)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ExecutionError", x => x.PersistenceId); + }); + + migrationBuilder.CreateTable( + name: "ScheduledCommand", + columns: table => new + { + PersistenceId = table.Column(type: "NUMBER(19)", nullable: false) + .Annotation("Oracle:Identity", "START WITH 1 INCREMENT BY 1"), + CommandName = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + Data = table.Column(type: "NVARCHAR2(500)", maxLength: 500, nullable: true), + ExecuteTime = table.Column(type: "NUMBER(19)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ScheduledCommand", x => x.PersistenceId); + }); + + migrationBuilder.CreateTable( + name: "Subscription", + columns: table => new + { + PersistenceId = table.Column(type: "NUMBER(19)", nullable: false) + .Annotation("Oracle:Identity", "START WITH 1 INCREMENT BY 1"), + SubscriptionId = table.Column(type: "RAW(16)", maxLength: 200, nullable: false), + WorkflowId = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + StepId = table.Column(type: "NUMBER(10)", nullable: false), + ExecutionPointerId = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + EventName = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + EventKey = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + SubscribeAsOf = table.Column(type: "TIMESTAMP(7)", nullable: false), + SubscriptionData = table.Column(type: "NVARCHAR2(2000)", nullable: true), + ExternalToken = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + ExternalWorkerId = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + ExternalTokenExpiry = table.Column(type: "TIMESTAMP(7)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Subscription", x => x.PersistenceId); + }); + + migrationBuilder.CreateTable( + name: "Workflow", + columns: table => new + { + PersistenceId = table.Column(type: "NUMBER(19)", nullable: false) + .Annotation("Oracle:Identity", "START WITH 1 INCREMENT BY 1"), + InstanceId = table.Column(type: "RAW(16)", maxLength: 200, nullable: false), + WorkflowDefinitionId = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + Version = table.Column(type: "NUMBER(10)", nullable: false), + Description = table.Column(type: "NVARCHAR2(500)", maxLength: 500, nullable: true), + Reference = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + NextExecution = table.Column(type: "NUMBER(19)", nullable: true), + Data = table.Column(type: "NVARCHAR2(2000)", nullable: true), + CreateTime = table.Column(type: "TIMESTAMP(7)", nullable: false), + CompleteTime = table.Column(type: "TIMESTAMP(7)", nullable: true), + Status = table.Column(type: "NUMBER(10)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Workflow", x => x.PersistenceId); + }); + + migrationBuilder.CreateTable( + name: "ExecutionPointer", + columns: table => new + { + PersistenceId = table.Column(type: "NUMBER(19)", nullable: false) + .Annotation("Oracle:Identity", "START WITH 1 INCREMENT BY 1"), + WorkflowId = table.Column(type: "NUMBER(19)", nullable: false), + Id = table.Column(type: "NVARCHAR2(50)", maxLength: 50, nullable: true), + StepId = table.Column(type: "NUMBER(10)", nullable: false), + Active = table.Column(type: "NUMBER(1)", nullable: false), + SleepUntil = table.Column(type: "TIMESTAMP(7)", nullable: true), + PersistenceData = table.Column(type: "NVARCHAR2(2000)", nullable: true), + StartTime = table.Column(type: "TIMESTAMP(7)", nullable: true), + EndTime = table.Column(type: "TIMESTAMP(7)", nullable: true), + EventName = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + EventKey = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + EventPublished = table.Column(type: "NUMBER(1)", nullable: false), + EventData = table.Column(type: "NVARCHAR2(2000)", nullable: true), + StepName = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + RetryCount = table.Column(type: "NUMBER(10)", nullable: false), + Children = table.Column(type: "NVARCHAR2(2000)", nullable: true), + ContextItem = table.Column(type: "NVARCHAR2(2000)", nullable: true), + PredecessorId = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + Outcome = table.Column(type: "NVARCHAR2(2000)", nullable: true), + Status = table.Column(type: "NUMBER(10)", nullable: false), + Scope = table.Column(type: "NVARCHAR2(2000)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ExecutionPointer", x => x.PersistenceId); + table.ForeignKey( + name: "FK_ExecutionPointer_Wf_WfId", + column: x => x.WorkflowId, + principalTable: "Workflow", + principalColumn: "PersistenceId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ExtensionAttribute", + columns: table => new + { + PersistenceId = table.Column(type: "NUMBER(19)", nullable: false) + .Annotation("Oracle:Identity", "START WITH 1 INCREMENT BY 1"), + ExecutionPointerId = table.Column(type: "NUMBER(19)", nullable: false), + AttributeKey = table.Column(type: "NVARCHAR2(100)", maxLength: 100, nullable: true), + AttributeValue = table.Column(type: "NVARCHAR2(2000)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ExtensionAttribute", x => x.PersistenceId); + table.ForeignKey( + name: "FK_ExtAttr_ExPtr_ExPtrId", + column: x => x.ExecutionPointerId, + principalTable: "ExecutionPointer", + principalColumn: "PersistenceId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Event_EventId", + table: "Event", + column: "EventId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Event_EventName_EventKey", + table: "Event", + columns: new[] { "EventName", "EventKey" }); + + migrationBuilder.CreateIndex( + name: "IX_Event_EventTime", + table: "Event", + column: "EventTime"); + + migrationBuilder.CreateIndex( + name: "IX_Event_IsProcessed", + table: "Event", + column: "IsProcessed"); + + migrationBuilder.CreateIndex( + name: "IX_ExecutionPointer_WorkflowId", + table: "ExecutionPointer", + column: "WorkflowId"); + + migrationBuilder.CreateIndex( + name: "IX_ExtensionAttribute_ExecutionPointerId", + table: "ExtensionAttribute", + column: "ExecutionPointerId"); + + migrationBuilder.CreateIndex( + name: "IX_ScheduledCommand_CommandName_Data", + table: "ScheduledCommand", + columns: new[] { "CommandName", "Data" }, + unique: true, + filter: "\"CommandName\" IS NOT NULL AND \"Data\" IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_ScheduledCommand_ExecuteTime", + table: "ScheduledCommand", + column: "ExecuteTime"); + + migrationBuilder.CreateIndex( + name: "IX_Subscription_EventKey", + table: "Subscription", + column: "EventKey"); + + migrationBuilder.CreateIndex( + name: "IX_Subscription_EventName", + table: "Subscription", + column: "EventName"); + + migrationBuilder.CreateIndex( + name: "IX_Subscription_SubscriptionId", + table: "Subscription", + column: "SubscriptionId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Workflow_InstanceId", + table: "Workflow", + column: "InstanceId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Workflow_NextExecution", + table: "Workflow", + column: "NextExecution"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Event"); + + migrationBuilder.DropTable( + name: "ExecutionError"); + + migrationBuilder.DropTable( + name: "ExtensionAttribute"); + + migrationBuilder.DropTable( + name: "ScheduledCommand"); + + migrationBuilder.DropTable( + name: "Subscription"); + + migrationBuilder.DropTable( + name: "ExecutionPointer"); + + migrationBuilder.DropTable( + name: "Workflow"); + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs new file mode 100644 index 000000000..63a882eef --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs @@ -0,0 +1,375 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Oracle.EntityFrameworkCore.Metadata; +using WorkflowCore.Persistence.Oracle; + +#nullable disable + +namespace WorkflowCore.Persistence.Oracle.Migrations +{ + [DbContext(typeof(OracleContext))] + partial class OracleContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("EventData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("EventId") + .HasColumnType("RAW(16)"); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("EventTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("IsProcessed") + .HasColumnType("NUMBER(1)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventId") + .IsUnique(); + + b.HasIndex("EventTime"); + + b.HasIndex("IsProcessed"); + + b.HasIndex("EventName", "EventKey"); + + b.ToTable("Event", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionError", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("ErrorTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("ExecutionPointerId") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("Message") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("WorkflowId") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.HasKey("PersistenceId"); + + b.ToTable("ExecutionError", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("Active") + .HasColumnType("NUMBER(1)"); + + b.Property("Children") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("ContextItem") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("EndTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("EventData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("EventKey") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("EventName") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("EventPublished") + .HasColumnType("NUMBER(1)"); + + b.Property("Id") + .HasMaxLength(50) + .HasColumnType("NVARCHAR2(50)"); + + b.Property("Outcome") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("PersistenceData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("PredecessorId") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("RetryCount") + .HasColumnType("NUMBER(10)"); + + b.Property("Scope") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("SleepUntil") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("StartTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("Status") + .HasColumnType("NUMBER(10)"); + + b.Property("StepId") + .HasColumnType("NUMBER(10)"); + + b.Property("StepName") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("WorkflowId") + .HasColumnType("NUMBER(19)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("WorkflowId"); + + b.ToTable("ExecutionPointer", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("AttributeKey") + .HasMaxLength(100) + .HasColumnType("NVARCHAR2(100)"); + + b.Property("AttributeValue") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("ExecutionPointerId") + .HasColumnType("NUMBER(19)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecutionPointerId"); + + b.ToTable("ExtensionAttribute", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedScheduledCommand", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("CommandName") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("Data") + .HasMaxLength(500) + .HasColumnType("NVARCHAR2(500)"); + + b.Property("ExecuteTime") + .HasColumnType("NUMBER(19)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecuteTime"); + + b.HasIndex("CommandName", "Data") + .IsUnique() + .HasFilter("\"CommandName\" IS NOT NULL AND \"Data\" IS NOT NULL"); + + b.ToTable("ScheduledCommand", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("ExecutionPointerId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("ExternalToken") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("ExternalTokenExpiry") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("ExternalWorkerId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("StepId") + .HasColumnType("NUMBER(10)"); + + b.Property("SubscribeAsOf") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("SubscriptionData") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("SubscriptionId") + .HasMaxLength(200) + .HasColumnType("RAW(16)"); + + b.Property("WorkflowId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventKey"); + + b.HasIndex("EventName"); + + b.HasIndex("SubscriptionId") + .IsUnique(); + + b.ToTable("Subscription", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("NUMBER(19)"); + + OraclePropertyBuilderExtensions.UseIdentityColumn(b.Property("PersistenceId"), 1L, 1); + + b.Property("CompleteTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("CreateTime") + .HasColumnType("TIMESTAMP(7)"); + + b.Property("Data") + .HasColumnType("NVARCHAR2(2000)"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("NVARCHAR2(500)"); + + b.Property("InstanceId") + .HasMaxLength(200) + .HasColumnType("RAW(16)"); + + b.Property("NextExecution") + .HasColumnType("NUMBER(19)"); + + b.Property("Reference") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.Property("Status") + .HasColumnType("NUMBER(10)"); + + b.Property("Version") + .HasColumnType("NUMBER(10)"); + + b.Property("WorkflowDefinitionId") + .HasMaxLength(200) + .HasColumnType("NVARCHAR2(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("InstanceId") + .IsUnique(); + + b.HasIndex("NextExecution"); + + b.ToTable("Workflow", (string)null); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", "Workflow") + .WithMany("ExecutionPointers") + .HasForeignKey("WorkflowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Workflow"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", "ExecutionPointer") + .WithMany("ExtensionAttributes") + .HasForeignKey("ExecutionPointerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ExecutionPointer"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Navigation("ExtensionAttributes"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Navigation("ExecutionPointers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/OracleContext.cs b/src/providers/WorkflowCore.Persistence.Oracle/OracleContext.cs new file mode 100644 index 000000000..b8fadcdf7 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/OracleContext.cs @@ -0,0 +1,74 @@ +using System; +using System.Linq; + +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +using Oracle.EntityFrameworkCore.Infrastructure; + +using WorkflowCore.Persistence.EntityFramework.Models; +using WorkflowCore.Persistence.EntityFramework.Services; + +namespace WorkflowCore.Persistence.Oracle +{ + public class OracleContext : WorkflowDbContext + { + private readonly string _connectionString; + private readonly Action _oracleOptionsAction; + + public OracleContext(string connectionString, Action oracleOptionsAction = null) + { + _connectionString = connectionString; + _oracleOptionsAction = oracleOptionsAction; + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + base.OnConfiguring(optionsBuilder); + optionsBuilder.UseOracle(_connectionString, _oracleOptionsAction); + } + + protected override void ConfigureSubscriptionStorage(EntityTypeBuilder builder) + { + builder.ToTable("Subscription"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } + + protected override void ConfigureWorkflowStorage(EntityTypeBuilder builder) + { + builder.ToTable("Workflow"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } + + protected override void ConfigureExecutionPointerStorage(EntityTypeBuilder builder) + { + builder.ToTable("ExecutionPointer"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } + + protected override void ConfigureExecutionErrorStorage(EntityTypeBuilder builder) + { + builder.ToTable("ExecutionError"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } + + protected override void ConfigureExetensionAttributeStorage(EntityTypeBuilder builder) + { + builder.ToTable("ExtensionAttribute"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } + + protected override void ConfigureEventStorage(EntityTypeBuilder builder) + { + builder.ToTable("Event"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } + + protected override void ConfigureScheduledCommandStorage(EntityTypeBuilder builder) + { + builder.ToTable("ScheduledCommand"); + builder.Property(x => x.PersistenceId).ValueGeneratedOnAdd(); + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/OracleContextFactory.cs b/src/providers/WorkflowCore.Persistence.Oracle/OracleContextFactory.cs new file mode 100644 index 000000000..54c70d6dc --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/OracleContextFactory.cs @@ -0,0 +1,29 @@ +using System; +using System.Linq; + +using Microsoft.EntityFrameworkCore.Infrastructure; + +using Oracle.EntityFrameworkCore.Infrastructure; + +using WorkflowCore.Persistence.EntityFramework.Interfaces; +using WorkflowCore.Persistence.EntityFramework.Services; + +namespace WorkflowCore.Persistence.Oracle +{ + public class OracleContextFactory : IWorkflowDbContextFactory + { + private readonly string _connectionString; + private readonly Action _oracleOptionsAction; + + public OracleContextFactory(string connectionString, Action oracleOptionsAction = null) + { + _connectionString = connectionString; + _oracleOptionsAction = oracleOptionsAction; + } + + public WorkflowDbContext Build() + { + return new OracleContext(_connectionString, _oracleOptionsAction); + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/README.md b/src/providers/WorkflowCore.Persistence.Oracle/README.md new file mode 100644 index 000000000..0e4957eea --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/README.md @@ -0,0 +1,19 @@ +# Oracle Persistence provider for Workflow Core + +Provides support to persist workflows running on [Workflow Core](../../README.md) to an Oracle database. + +## Installing + +Install the NuGet package "WorkflowCore.Persistence.Oracle" + +``` +PM> Install-Package WorkflowCore.Persistence.Oracle -Pre +``` + +## Usage + +Use the .UseOracle extension method when building your service provider. + +```C# +services.AddWorkflow(x => x.UseOracle(@"Server=127.0.0.1;Database=workflow;User=root;Password=password;", true, true)); +``` diff --git a/src/providers/WorkflowCore.Persistence.Oracle/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Persistence.Oracle/ServiceCollectionExtensions.cs new file mode 100644 index 000000000..4a46b0e5c --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/ServiceCollectionExtensions.cs @@ -0,0 +1,24 @@ +using System; +using System.Linq; + +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.Extensions.DependencyInjection; + +using Oracle.EntityFrameworkCore.Infrastructure; + +using WorkflowCore.Interface; +using WorkflowCore.Models; +using WorkflowCore.Persistence.EntityFramework.Services; + +namespace WorkflowCore.Persistence.Oracle +{ + public static class ServiceCollectionExtensions + { + public static WorkflowOptions UseOracle(this WorkflowOptions options, string connectionString, bool canCreateDB, bool canMigrateDB, Action mysqlOptionsAction = null) + { + options.UsePersistence(sp => new EntityFrameworkPersistenceProvider(new OracleContextFactory(connectionString, mysqlOptionsAction), canCreateDB, canMigrateDB)); + options.Services.AddTransient(sp => new WorkflowPurger(new OracleContextFactory(connectionString, mysqlOptionsAction))); + return options; + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj b/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj new file mode 100644 index 000000000..1c80bad68 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj @@ -0,0 +1,43 @@ + + + + Workflow Core Oracle Persistence Provider + 1.0.0 + Christian Jundt + net6.0 + WorkflowCore.Persistence.Oracle + WorkflowCore.Persistence.Oracle + workflow;.NET;Core;state machine;WorkflowCore;Oracle + https://github.com/danielgerlag/workflow-core + https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md + git + https://github.com/danielgerlag/workflow-core.git + false + false + false + Provides support to persist workflows running on Workflow Core to a Oracle database. + + + + + all + runtime; build; native; contentfiles; analyzers + + + 6.21.61 + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + diff --git a/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs b/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs index 1e082f4db..a5819d2fa 100644 --- a/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs +++ b/test/WorkflowCore.IntegrationTests/Scenarios/ActivityScenario.cs @@ -43,7 +43,7 @@ public void Build(IWorkflowBuilder builder) public ActivityScenario() { - Setup(); + Setup(); //NOTE cjundt [10/03/2023] setup shouldn't be here in constructor. It prevents from using ICollectionFixture data. } [Fact] diff --git a/test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs b/test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs new file mode 100644 index 000000000..c4445f005 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs @@ -0,0 +1,25 @@ +using System; +using WorkflowCore.Interface; +using WorkflowCore.Persistence.EntityFramework.Services; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; +using WorkflowCore.UnitTests; +using Xunit; +using Xunit.Abstractions; + +namespace WorkflowCore.Tests.Oracle +{ + [Collection("Oracle collection")] + public class OraclePersistenceProviderFixture : BasePersistenceFixture + { + private readonly IPersistenceProvider _subject; + protected override IPersistenceProvider Subject => _subject; + + public OraclePersistenceProviderFixture(OracleDockerSetup dockerSetup, ITestOutputHelper output) + { + output.WriteLine($"Connecting on {OracleDockerSetup.ConnectionString}"); + _subject = new EntityFrameworkPersistenceProvider(new OracleContextFactory(OracleDockerSetup.ConnectionString), true, true); + _subject.EnsureStoreExists(); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/OracleSetup.cs b/test/WorkflowCore.Tests.Oracle/OracleSetup.cs new file mode 100644 index 000000000..8b35d9aa2 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/OracleSetup.cs @@ -0,0 +1,26 @@ +using System; +using System.Threading.Tasks; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle +{ + public class OracleDockerSetup : IAsyncLifetime + { + public static string ConnectionString => "Data Source=(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = ORCLPDB1) ) );User ID=TEST_WF;Password=test;"; + + public async Task InitializeAsync() + { + } + + public Task DisposeAsync() + { + return Task.CompletedTask; + } + } + + [CollectionDefinition("Oracle collection")] + public class OracleCollection : ICollectionFixture + { + } +} \ No newline at end of file diff --git a/test/WorkflowCore.Tests.Oracle/Properties/AssemblyInfo.cs b/test/WorkflowCore.Tests.Oracle/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..24072c66f --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Properties/AssemblyInfo.cs @@ -0,0 +1,18 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WorkflowCore.Tests.Oracle")] +[assembly: AssemblyTrademark("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("8c2bd4d2-43ec-4930-9364-cda938c01803")] diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleActivityScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleActivityScenario.cs new file mode 100644 index 000000000..eeae8ea66 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleActivityScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleActivityScenario : ActivityScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleBasicScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleBasicScenario.cs new file mode 100644 index 000000000..8cb898583 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleBasicScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleBasicScenario : BasicScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDataScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDataScenario.cs new file mode 100644 index 000000000..f71630c93 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDataScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleDataScenario : DataIOScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs new file mode 100644 index 000000000..55062f0c3 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs @@ -0,0 +1,23 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleDelayScenario : DelayScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(cfg => + { + cfg.UseOracle(OracleDockerSetup.ConnectionString, true, true); + cfg.UsePollInterval(TimeSpan.FromSeconds(2)); + }); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDynamicDataScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDynamicDataScenario.cs new file mode 100644 index 000000000..e59f51d51 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDynamicDataScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleDynamicDataScenario : DynamicDataIOScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleEventScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleEventScenario.cs new file mode 100644 index 000000000..ac987c341 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleEventScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleEventScenario : EventScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForeachScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForeachScenario.cs new file mode 100644 index 000000000..fb2fcc965 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForeachScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleForeachScenario : ForeachScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForkScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForkScenario.cs new file mode 100644 index 000000000..d525de700 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForkScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleForkScenario : ForkScenario + { + protected override void Configure(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleIfScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleIfScenario.cs new file mode 100644 index 000000000..c090f89d1 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleIfScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleIfScenario : IfScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleRetrySagaScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleRetrySagaScenario.cs new file mode 100644 index 000000000..01c651a7c --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleRetrySagaScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleRetrySagaScenario : RetrySagaScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleSagaScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleSagaScenario.cs new file mode 100644 index 000000000..7775638c2 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleSagaScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleSagaScenario : SagaScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleUserScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleUserScenario.cs new file mode 100644 index 000000000..0e5861f6d --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleUserScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleUserScenario : UserScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhenScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhenScenario.cs new file mode 100644 index 000000000..b8671695e --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhenScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleWhenScenario : WhenScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhileScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhileScenario.cs new file mode 100644 index 000000000..0b4b01467 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhileScenario.cs @@ -0,0 +1,19 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using WorkflowCore.IntegrationTests.Scenarios; +using WorkflowCore.Persistence.Oracle; +using WorkflowCore.Tests.Oracle; + +using Xunit; + +namespace WorkflowCore.Tests.Oracle.Scenarios +{ + [Collection("Oracle collection")] + public class OracleWhileScenario : WhileScenario + { + protected override void ConfigureServices(IServiceCollection services) + { + services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); + } + } +} diff --git a/test/WorkflowCore.Tests.Oracle/WorkflowCore.Tests.Oracle.csproj b/test/WorkflowCore.Tests.Oracle/WorkflowCore.Tests.Oracle.csproj new file mode 100644 index 000000000..db77aa957 --- /dev/null +++ b/test/WorkflowCore.Tests.Oracle/WorkflowCore.Tests.Oracle.csproj @@ -0,0 +1,21 @@ + + + + net6.0 + WorkflowCore.Tests.Oracle + WorkflowCore.Tests.Oracle + true + false + false + false + + + + + + + + + + + From e7219e5d3025b144c08e6f8ab74c0863373e289e Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Thu, 6 Apr 2023 07:34:08 -0700 Subject: [PATCH 256/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 8793e7e27..a617157cb 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.8.1 - 3.8.1.0 - 3.8.1.0 + 3.8.2 + 3.8.2.0 + 3.8.2.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.8.1 + 3.8.2 From b06b690691d47222075c57ecc0f6a3394b27b781 Mon Sep 17 00:00:00 2001 From: Stuart McKenzie Date: Thu, 27 Apr 2023 14:54:17 +1000 Subject: [PATCH 257/342] add alternate constuctor arguments to allow supply of provisioned sqs and dynamo clients --- .../WorkflowCore.Providers.AWS/README.md | 12 +++++++++ .../ServiceCollectionExtensions.cs | 27 ++++++++++++++++--- .../Services/DynamoDbProvisioner.cs | 4 +-- .../Services/DynamoLockProvider.cs | 4 +-- .../Services/DynamoPersistenceProvider.cs | 4 +-- .../Services/SQSQueueProvider.cs | 4 +-- .../DynamoPersistenceProviderFixture.cs | 4 +-- 7 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/providers/WorkflowCore.Providers.AWS/README.md b/src/providers/WorkflowCore.Providers.AWS/README.md index f9c000662..0a9286f37 100644 --- a/src/providers/WorkflowCore.Providers.AWS/README.md +++ b/src/providers/WorkflowCore.Providers.AWS/README.md @@ -34,6 +34,18 @@ services.AddWorkflow(cfg => If any AWS resources do not exists, they will be automatcially created. By default, all DynamoDB tables and indexes will be provisioned with a throughput of 1, you can modify these values from the AWS console. You may also specify a prefix for the dynamo table names. +If you have a preconfigured dynamoClient, you can pass this in instead of the credentials and config +```C# +var client = new AmazonDynamoDBClient(); +var sqsClient = new AmazonSQSClient(); +services.AddWorkflow(cfg => +{ + cfg.UseAwsDynamoPersistenceWithProvisionedClient(client, "table-prefix"); + cfg.UseAwsDynamoLockingWithProvisionedClient(client, "workflow-core-locks"); + cfg.UseAwsSimpleQueueServiceWithProvisionedClient(sqsClient, "queues-prefix"); +}); +``` + ## Usage (Kinesis) diff --git a/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs index 57b6f6bc8..171860524 100644 --- a/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs @@ -15,20 +15,39 @@ public static class ServiceCollectionExtensions { public static WorkflowOptions UseAwsSimpleQueueService(this WorkflowOptions options, AWSCredentials credentials, AmazonSQSConfig config, string queuesPrefix = "workflowcore") { - options.UseQueueProvider(sp => new SQSQueueProvider(credentials, config, sp.GetService(), queuesPrefix)); + options.UseQueueProvider(sp => new SQSQueueProvider(credentials, config, null, sp.GetService(), queuesPrefix)); + return options; + } + + public static WorkflowOptions UseAwsSimpleQueueServiceWithProvisionedClient(this WorkflowOptions options, AmazonSQSClient sqsClient, string queuesPrefix = "workflowcore") + { + options.UseQueueProvider(sp => new SQSQueueProvider(null, null, sqsClient, sp.GetService(), queuesPrefix)); return options; } public static WorkflowOptions UseAwsDynamoLocking(this WorkflowOptions options, AWSCredentials credentials, AmazonDynamoDBConfig config, string tableName) { - options.UseDistributedLockManager(sp => new DynamoLockProvider(credentials, config, tableName, sp.GetService(), sp.GetService())); + options.UseDistributedLockManager(sp => new DynamoLockProvider(credentials, config, null, tableName, sp.GetService(), sp.GetService())); + return options; + } + + public static WorkflowOptions UseAwsDynamoLockingWithProvisionedClient (this WorkflowOptions options, AmazonDynamoDBClient dynamoClient, string tableName) + { + options.UseDistributedLockManager(sp => new DynamoLockProvider(null, null, dynamoClient, tableName, sp.GetService(), sp.GetService())); return options; } public static WorkflowOptions UseAwsDynamoPersistence(this WorkflowOptions options, AWSCredentials credentials, AmazonDynamoDBConfig config, string tablePrefix) { - options.Services.AddTransient(sp => new DynamoDbProvisioner(credentials, config, tablePrefix, sp.GetService())); - options.UsePersistence(sp => new DynamoPersistenceProvider(credentials, config, sp.GetService(), tablePrefix, sp.GetService())); + options.Services.AddTransient(sp => new DynamoDbProvisioner(credentials, config, null, tablePrefix, sp.GetService())); + options.UsePersistence(sp => new DynamoPersistenceProvider(credentials, config, null, sp.GetService(), tablePrefix, sp.GetService())); + return options; + } + + public static WorkflowOptions UseAwsDynamoPersistenceWithProvisionedClient(this WorkflowOptions options, AmazonDynamoDBClient dynamoClient, string tablePrefix) + { + options.Services.AddTransient(sp => new DynamoDbProvisioner(null, null, dynamoClient, tablePrefix, sp.GetService())); + options.UsePersistence(sp => new DynamoPersistenceProvider(null, null, dynamoClient, sp.GetService(), tablePrefix, sp.GetService())); return options; } diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs index 3f381c8c3..6d3c712b7 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs @@ -15,10 +15,10 @@ public class DynamoDbProvisioner : IDynamoDbProvisioner private readonly IAmazonDynamoDB _client; private readonly string _tablePrefix; - public DynamoDbProvisioner(AWSCredentials credentials, AmazonDynamoDBConfig config, string tablePrefix, ILoggerFactory logFactory) + public DynamoDbProvisioner(AWSCredentials credentials, AmazonDynamoDBConfig config, AmazonDynamoDBClient dynamoDBClient, string tablePrefix, ILoggerFactory logFactory) { _logger = logFactory.CreateLogger(); - _client = new AmazonDynamoDBClient(credentials, config); + _client = dynamoDBClient ?? new AmazonDynamoDBClient(credentials, config); _tablePrefix = tablePrefix; } diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs index 6f4aca0e8..32ebe488b 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs @@ -25,10 +25,10 @@ public class DynamoLockProvider : IDistributedLockProvider private readonly AutoResetEvent _mutex = new AutoResetEvent(true); private readonly IDateTimeProvider _dateTimeProvider; - public DynamoLockProvider(AWSCredentials credentials, AmazonDynamoDBConfig config, string tableName, ILoggerFactory logFactory, IDateTimeProvider dateTimeProvider) + public DynamoLockProvider(AWSCredentials credentials, AmazonDynamoDBConfig config, AmazonDynamoDBClient dynamoDBClient, string tableName, ILoggerFactory logFactory, IDateTimeProvider dateTimeProvider) { _logger = logFactory.CreateLogger(); - _client = new AmazonDynamoDBClient(credentials, config); + _client = dynamoDBClient ?? new AmazonDynamoDBClient(credentials, config); _localLocks = new List(); _tableName = tableName; _nodeId = Guid.NewGuid().ToString(); diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs index 09f1dbc4c..0c78c6048 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs @@ -26,10 +26,10 @@ public class DynamoPersistenceProvider : IPersistenceProvider public bool SupportsScheduledCommands => false; - public DynamoPersistenceProvider(AWSCredentials credentials, AmazonDynamoDBConfig config, IDynamoDbProvisioner provisioner, string tablePrefix, ILoggerFactory logFactory) + public DynamoPersistenceProvider(AWSCredentials credentials, AmazonDynamoDBConfig config, AmazonDynamoDBClient dynamoDBClient, IDynamoDbProvisioner provisioner, string tablePrefix, ILoggerFactory logFactory) { _logger = logFactory.CreateLogger(); - _client = new AmazonDynamoDBClient(credentials, config); + _client = dynamoDBClient ?? new AmazonDynamoDBClient(credentials, config); _tablePrefix = tablePrefix; _provisioner = provisioner; } diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/SQSQueueProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/SQSQueueProvider.cs index dd1c15e14..af2c40b20 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/SQSQueueProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/SQSQueueProvider.cs @@ -21,10 +21,10 @@ public class SQSQueueProvider : IQueueProvider public bool IsDequeueBlocking => true; - public SQSQueueProvider(AWSCredentials credentials, AmazonSQSConfig config, ILoggerFactory logFactory, string queuesPrefix) + public SQSQueueProvider(AWSCredentials credentials, AmazonSQSConfig config, AmazonSQSClient sqsClient, ILoggerFactory logFactory, string queuesPrefix) { _logger = logFactory.CreateLogger(); - _client = new AmazonSQSClient(credentials, config); + _client = sqsClient ?? new AmazonSQSClient(credentials, config); _queuesPrefix = queuesPrefix; } diff --git a/test/WorkflowCore.Tests.DynamoDB/DynamoPersistenceProviderFixture.cs b/test/WorkflowCore.Tests.DynamoDB/DynamoPersistenceProviderFixture.cs index 6fb9c1ea9..6ec1c13b6 100644 --- a/test/WorkflowCore.Tests.DynamoDB/DynamoPersistenceProviderFixture.cs +++ b/test/WorkflowCore.Tests.DynamoDB/DynamoPersistenceProviderFixture.cs @@ -26,8 +26,8 @@ protected override IPersistenceProvider Subject if (_subject == null) { var cfg = new AmazonDynamoDBConfig { ServiceURL = DynamoDbDockerSetup.ConnectionString }; - var provisioner = new DynamoDbProvisioner(DynamoDbDockerSetup.Credentials, cfg, "unittests", new LoggerFactory()); - var client = new DynamoPersistenceProvider(DynamoDbDockerSetup.Credentials, cfg, provisioner, "unittests", new LoggerFactory()); + var provisioner = new DynamoDbProvisioner(DynamoDbDockerSetup.Credentials, cfg, null, "unittests", new LoggerFactory()); + var client = new DynamoPersistenceProvider(DynamoDbDockerSetup.Credentials, cfg, null, provisioner, "unittests", new LoggerFactory()); client.EnsureStoreExists(); _subject = client; } From 1820211a7a554509dda9f4370e21495281594e03 Mon Sep 17 00:00:00 2001 From: Peeyush Chandel <555114+cpeeyush@users.noreply.github.com> Date: Thu, 27 Apr 2023 08:42:50 +0200 Subject: [PATCH 258/342] Add performance test results under doc section --- .../performance-test-workflows-latency.png | Bin 0 -> 119222 bytes .../performance-test-workflows-per-second.png | Bin 0 -> 80363 bytes docs/performance.md | 87 ++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 docs/images/performance-test-workflows-latency.png create mode 100644 docs/images/performance-test-workflows-per-second.png create mode 100644 docs/performance.md diff --git a/docs/images/performance-test-workflows-latency.png b/docs/images/performance-test-workflows-latency.png new file mode 100644 index 0000000000000000000000000000000000000000..621fc276012896c488076675032629229042634f GIT binary patch literal 119222 zcmeEv30PCt+HTaUZ5=qRRvZwjZNUMF3KCEt&J;1AQblA^Q4kPo<|9Lui+csZ&=@2 zdvooOh3TSiSAGkF!4{eQy7veS_8kQVTY&v~4!8nW;OfDTS>8uXcf&HP)mY${uUvMa zcEMmTq83O`&4s~c&p&kVw|&jc%}q^BEiEmrt*zky$&cpVfF0Jq8y&xFav}_Adllsp zZh7w7k@JzidET_Kv9ZNB*n7u2I5;>tIk~#Jy8li%pIqnhnC9u}iB4_sN^A5=Yw~*1 z>h;{z+uPeW@pMNC)W;_UWv=I56!p#J+u1v0*A}sljnXVyY@)Qu6vE<4r|lX)&p^oca!Y8psv39hH>)%F4>B+QzE-@)`!awzjsu=R*Vd zbksJsGaH$FASfWQHb!6D;K%mrxAZqz^v2>&@EI2N^z`%&jPwpOdO7WV75RNl)V{vH zen$DgUE9Gw_78#&S3GphbSTzgh|L`y9%hGZVUG`t+&I9AH0R(?b2yw)@DWJ3NoTpG zx?JH1ujwuSSpdIm8=u)eo_}Nfo&NavxL~AF_}*Zm!cg>PrRc+Uap@{Cy;3X|OWvwU zs*EJeW@*`KDb-lU>67t><>eZR5}4xskBZuzipJxLb}t2oqTtmigbanKU!hPmw?tF| zh|KpnVqx{`$$(f!ztI0;dknbrjn}U>-Z0qK66oKob!Ser!C*3++1_2h1vm_MFe20( zah?A2^(&~JN5-n`s!(TMUk}^7DobDeweHtle>iVxwg2UI@>h2Qbnd>swt1J0*FP#t zy6w)~h|LZN*M5B&rSs;p#{hDxeVT>h$%r^%M19;; z!u8{30csu`!}T*HkvJssE9kfVir47g`QRI@{wW*b1brEN%uxQ0qCoAR;IWW7974$E zfgcY%#f!j?ogMsD;72Htg#bTbzBDxSV=(pajzA3mv2ap7(Vp1e@aHLIj*mELC~v>2 z9bK`bh<3Ld2rU$^TL%s+`R*ec7CP*$yXC`zjS;3pRy%IOF{jL9qhpiQ#?C7WrHjn- zSM^ZgC!=7aMnDONqBsoh?r4z|BDkdr>kJq`z|>O0@h$;2@B5=Gs4nE9E8y0Nx*GY&B5)%`l8E5W)#uWpSr}plEG?GxV>F` ze&2GM#`swWSZL2f2F&Yj>k3<*A>3$*(De{iNPacHl5l(&AyEX9xD(iDi-w8&s+z53 zZi`8g@*gcfqOr_hU)erEJda+TP@BhI&d9H!R4;&e=>e?XJhEd>P^!#1s;OTa*R3gI zew}q9$cKVCS5sg^4!R)OpEr)@YV>|1p*r2XBIqZ_1XJ0IzN{q?GA7IsZK~dZF3yMBfze2Imil(`%L`Yx0ix7#KewZJ z)QYk)epip@!Q690TZ-KrJGI`C>3K&u^Ca<4mn-O z7*-6i-zQ5@#9HUEb?&i4EJP*l)jm zulE75J57rHoBP-tcQL94B_Ud4*0@>^AfjT5tKQVSuxt;JiiYmzYd8`8D(C(NQ(GaM z7n)pOP2uD1Y3M+D7CF=YA;YM(Qcy{*UO>u`EvJRq>O7d;`F@fvc?x4V9!vA47mwIF z{Mz~hU?hd+K<^LhXu;lawJZ$%HuR@trRGJk5DC;rd|g@^<{>Q;NbhaEyfv)^SpcI_2+4M`$Y*}4vPA$Ip4+ehtBuJjvc_3ldd_be;$S7poG9PO|t zh+E#Vd*eDD^G5ba(#u_93G-dBLdQ%^yrqr~vV*ye;GAXWB|N1k-Wn z3n~F8kvH_RRMGt$U&Ygqa8-0B?_$0Z*8JYaagvW&RYZX!_xju}`EbU_^EeF+$27+P zY$4Hu7IKj%=sv@pXYJS)b_r`G?zYlsbFpKFS&&kj(cd~6i^j$}dff?*WDnult+*3j z_4&@F#XYQm zGMI9B*3Q03l*_Jb)*&-Bt%PyW{wkOdp+<*l;z2}Yxntc8ogfDO$5d9=nXRH*BjI-v zo@0F^R@-%B8Er>dU){WCb2|R4ip6PUt}UGzhC=##ilvhJjdu{39|@W{qt*M+=k^em z3-BpgQRRrImwc*Cdhgks!sX8sG}brinG=Z8+t&X2ZCVT_daS!`CuM!eSRwzVyupO^ z!x-biM1$4{kx?^(i7VJ=>algTz!zH`k?Yr`^1XUn4y7x+r47!`W(6VT*{(mxA9%Cw z-(MVXh_62+tUf}q@s<{OTBC6Xmci8SVCR$^K0tf<`WpX@o?cL#LJ}l4d{|tOyRFdv zer-YZGOY)g-%0b&GHiwyRS=^)@u5Dn3?@rdQC{0?FLHgBA$&|>D(X%>+A<`0J{m*ybN3RALrg)@SXL zmi*S#qi&I8`*ZYjK7O=$B*{DHx0}oSn>%$n2D8`8b_H?O|CoJzLLWbzSeBJDGJ%(G ztODLuO^LhsyNjyl&|;X>fl4a1=`c~X;{5k=LH8q4*t?3}T^nmy9HNzq&VGc@ACc_2 zviQ*PI{v6tJfk>Z2l0c;)`WvK9j>V8l5~H^{b(ZM97AFoSdV1<7?L8-)3P$>)h;qA zaOo0d(W6==lw1>k-YBmixia`_8A&R=_RzB3>qVQZi-y*c9u3DV3su4^XWafE_ihtQ zvSYEr$GfAW=IrT*`r0?Pv}!qWi3Q0Y+dP8;#TksH#Q~PW@}csATsH$`hHMa7*JL2k zGhB`~@iR^_o=2)2s_Py-+;*U}`dVK@FOE2rwoLKk#}|o7yhpjE%lueBso>vexy zG=K;s4((0Vtq%9`*vH!fXR=OhWElKRsLI}as>)l)Lhbf!<;|^YOJQB)_+KY2`9#shi7g$W%rc*2!N~3SwCmd>y6v_- z7yNPeX{?G>{u{l=J-=GgWr7*dF+3_Ol0!49TF1YuP@N zt(-cOcna;zL!bK8Qw4jBUHyBaR635@o8t(toq}YG@y0zL!%4TVSU9D6=}(rLdYh_lmovJ>57rjwYJtj-1DQ#kvw19k${u zk@{YWY_`;Tl@sI{Y`Nq;O;qkv^C~`TBDgitm)4PeW^DLYuCwb+<2*eTdqrUgt)Ei8 zq%*wbtX59CDUl@CNqL$Aah-VTrO(j=E;%y8>;mq%Za~$Xu=6{1goL4g2@`fVl&a zVd;Cg>(z2tZb_ZRNtQ6uH@(vO>wKx)Rlfs%#UHWJAwe@WXY*A{i{(knR89OVKJe0- zk`roXAMrQsv&OhiEJ4_vFE=W}9by0*<~$#{=R)J(@%iD5Kxn(7=YxqE2Wzt6r<^mJ z+xo{;Ip$q1CgR8T+k%^)%Ldoa-;^*I{b={nf5b$!8V#qAUTMoh4#-loOOGYJV4t#@ zxSaWl;BdTA4<1{MZIOD+6IKT!GbF-<$Gn%z2w%Y(Kr(M|fIaMKIG1AXLJYcb&}T_|EN_KZ(#~pnE@{(HXW4QV&4r^^6zql_+*t$s5xZZ9m4tgS zD%Fc-Q^mC25EH4=O6?6;as;F*jR1o6V6|^Q6M{e0<%mdgC78Uf*;fe^g0n zfE(D7skQXDki_3z$6zz!s>-^!BkX6dOFd=Qmgs`f zD;jL>8W?vKa!_U*1{@AkMVs2(25kO7S( zW>5Td40gy^86q^#tQyCsn2ijoA*j7EOdc!nHmmO^b5896@3$?_^wz8{UYbhco-t`S z80)dr@ulF_d4sud-q2p;AW~F=UdT@xN*JVkyCfXC`H1pxqC>(IN!#%-0H6-DA({s zMoyKbsa_K*5+k^Q7B8`|tW7(lPu|^%t1;XDZJ?_Atex!1q(st+qF{cFjn=mRcz0_h zf8MI}CGGNOBirLdY=gkMr?Yb$w;YHT$XnJdxK67(bF!g*@STsq61|q*amz(NdJ{x- z#FDg)O{9!A!Wey}9Q9yim8GIS-O296J?BC5OBoFGBY3g4u?H)$j(Dlm^Kw>FrpTsw zQxp5*@_&55T|19qUzIttgV6rXOH~vlyI;rAvjXr1>myIfDE&XLUed*~gdO^6GLtR# zqoIkI9+czu#M9gT9TPhR*1iRHHm_{oKN@+rj^=*2ZYZXDah$FAfiHn{-q%U&Ec+&e zwJgp4X2a<&;I3kVq7SNqgy!41zrYY_=C;pt{^T(p+?jEBJR_|>m z-giI!&D}2~pX_HXb0(E)$}h**rR{liPgtXmwp#gG3*FIZDS#2mW23aZ#)mh$N0@VMt$zt?zy(OuiImL z!`bd(S$A_2yCwkbEBy9E%N>h`W^zIGbN^U})ZA(xT!(;yPEX zM%ReW8(HmAjl4OfNyi<6?qjV?q)r6dTsM?=-8Ot4I;V?nqu>~tWr4-2!3M|^u1CFp zg!L}kTsc(LAGp!GeWWpCPpYu{xKfPBglN@cj~UlY*i1I-OhR;+qnPzcjy=%={8*I8 zvpAlBc;ShA7qrpCMs}9NUr&p&U+siDiU=Y^X64kQe}@;JN#~*UCkBP5A3sk;XM07&X?TNcoOUC;rrO4-HUPdM;4YoJJ<3{sHX2sIrs(ZT{oR z#8eFucXiA$k9zb~%EZguJViuj*QtUEYtHPlbiol~_>j-q#^IO5Yuv*-HV&hWlt(kh#hA@%({302rqFYVj6(Y|ymVd#0)1zN}%{KxB- zIp&7Pv|h=MvOe6OsJi6S(>fA+o#t;NwPzNmsGJZMRvtr`T%fFo;vlO%_e$1svXrjs zb&MW}$g!6=wYCkwg^-#u`S{nsU{;&Tti!@PG#zCo_FJ}HNP?@KkQO}yL9irSE2c?3 zm62g6ji{qUdLr-Ao$*RSxv3#B48rWrC(8Alp4qBFgs_7wmGjkKzT;$c~@ub-LGC(F^3(+cwCtlbG_tIU2d*!wwtGKkBOLi=KG||y+Vn} zkidmpK-^TB75uAvn(#aIiN&&`>^JcYLOcsMc9zu}m(rD*rlRJzDtH_)4IICNwme~+ znCutO1kW-)2$nPxu_?G!EWP`0+Ro?sH!6ZG0%P-Ml^m{xVz28R{mr*WPFLW`^(W#X z<&z}!Iu@z1&n>(p>BQ)--#FeI#2OM4lT&G1zSXUqA`mO4@*8zJS{6={7boOyB!GUk|sbM~fYUTWS{~jYB%K+d9(=9EaVcG8BUgI<#2v z$j2Eqh!|@-U!bI~Za&nH@}0n3;53nl)kWUDROc8GlHH@cT!b#7>>(2N3$# z`hRD=d|J_q2q{p-^xc}Guvm=pcRpOabutHtPlMxj65$_Q9hQrM09hGvO_((i5)=nS zAFY1!hXpnyx6$0JJV)cagb`w9+r6QTM)kZ>5*EWgC8iQfDZOio^38R-+RhjHH_C%7 z>NGNh5x>C>?fBD^U)8MZpgJ$Z9XaQk8LLAZkkxq;qg`3C=Kwa%)9a3I5ox^%f4rhE ze8ecB?(PeNO{htqX-i>MBUzr?Un>1j;@C?mZ;*8*-saW{NYAXBuUMXYbUQlG;Sy@M zs^cBH|FWCgSuJ}>4}q@9bk8lV{2v&2)4i1)f(az6in&ra5DWbOABilXz}PF*PR0 zg-z){CQSD-Z)*AE+T*c{4nC%>|GLP`pNM%EoY{nG=IySt-(z+E15kVHv6N_o7@by| zglD*O2+BYz?{(DbU&>rvwMNtM=zsH+!;v}ne-z3{e8X|Ogmojik4HW7 z+jqDtj0=b)_Fegw**kqF*Lx7TB*g>DX1IAYC9KfFKj=nT#1{1<*6XG7C3#kzBPLq# zWgAPW!`z zrxPua1mR^8fAL|8jT8hX$_d5(4XzD`C^nJ?8ln4)Ui-FBKp1>c^m_5CfOj$B01!B4 znW!%ETHSn<|KSOJ+Yu-gw3VfEVV&zH%TMBMdbdYBpKMV)jUPe2gIieA%Jk4c&N4DJ zU5>kn5|e5FR9Tk8WPvAZ968e$e5++Wx8s0tDRGK z_$pZ-zR57eGrC14?8303{O#{vqg%-F&Y_%+76cD#1ww1x?K=2kc6=A53#_(R-$!`| zehk!I8B!P*dmUf}c-v!*nd)u$k!-qdzVZ3S)pDz7t)k;bb6J}AVp?==(w*Ciz>3>F zrC+;4^BdTPG^j#Wx0HP`cVJJvgCC_fA#FhD8ffxjGk!SfR%!!-R52ccC_^UJjCvxA zjvGXsk}Z9;W6uLaj)_2EzoW}8co*@qX*$j+=Bzn~DEF3tsBwydF^*ef>EFD^pH-=M zRGDcJIhy=5n!mVi6TB+Ny8IP+Fmu5#s;)PL$$smf#|iLn0QzSiq+ETRrn1^^h!W@@ zcC@B1Ljc_J{Hw+PCPnB6^8YHWdPH$CZYHsEdKKwW~P-N95$$3d=bApJ~7 z+sD|f{M;&1>UUoxz-&*Hl$iMbu?l@(%cqmfG^KxzAGkJ376ClsuYgnJ3ss zW};2VL;DemA4axGa=?PoG0U)MdE|aoOjaU1!R*EMclVBV#BFAyeH?u`UU%ret>^=e zWOxWwu5u`)A6_BxXIm@oHf?R1cY0T_nl3#Z*Y9Wa z4tXt0tV&B+LQB0>v*v36K1~AYoNvz(0iN}Tvx9cRiQnjil%nxpEQ?ghb^$$?wq#}m z4rG?b8H(cP8M6^(aC)@cuZkN_`M;mVv_U1Fg^hPuz7Fm;TQ8lm%*eDi&TrymH@KYd zKm)Y3WYlOMf7Pvx#d`>=i9K+JyNkX$%-~z)+LrYAv{@_n7QAvGq2uuqoxo^P7)HRa zi`0l%!l>>W7W_PvRbYum6$v{2LjQnaQyxU@JrZ&4ar69EAH~#nYO~peKccX3JvPcy#%t&x3kin)LOL&&W_I|WyyZEG*Cx~fCtb_l7**INccUnketpA#fNhZn!1NPFJdagz zwp}zP5?{S~B~6e=OFF_omdkN{8jKrs2RpL*xJy(4fzivDM;uZ3P)oD;k&W3G6Bx2pmhecIM=b%aUGkh-4nxd)CC*3&jntD#46m)xlX_ zR_eJ{I{0)sAAMiq#F8exIlMz}_$0gTMG^MTb)(gGsj5*hs+9aHK;bJ|eP;ktURY1o zjvTiMwKcFOF<{#<=$6hxRvOIBpMf0eb$PrhQ(GakqG4iHn+ZObn%`ioU|vf>I0^_< zVGXWOJ+Bt$({|5iZez`XChbiM2VWuq?XykIQi~lxQD0p00xVKGS-wJ4OGTX8uq82c z(AQyNJxiLdf;qLJZ_SERiaM%Kqg~b4um)wzJW6bj(DP>X9x?Ta{h0!OdS5JN4auA% z-v)nyU~!+uVrIc^UIkQI>U78+i|)o6tYqcJ+1m+XuxnYl{-oY;{sJ?1?2#m`TUcvt zd89V%$=%7;=$!yQG-Lwmqh zNQu?Zhy&SYd|~;IiJ>_WR@>@|JmZ;sH$IEWqz!mjquYxnV0A^0{V!U(!J0RMUD~8p z-}q;^3UjsFK7DOEAKL7RE+bn-Ojs-BN@XL=U^lR8qdcFHvZpJ0wh$AfEWe9=ZL&7O z%fuvIGY+gcpG1cWmTRDqnnU6 zuR-h4dXuRAKM9|nHIfU?>IHgV7{l_r_JgAm`H%kI68^Wgg#X@X|NAh(-zP2pYfh8o zJk&sPFVBiNxTaDc+n zPp~JGg5%V;ad=m+ed>HN4oedUHiq53mV)IK+WT|I9)`5jHC(#gTQ`rr_ehC_PTXYF zqTls|r!PJ1fOAuzDGZ~>*}9}XsKD+@^5|5XI?yJ{W49qmosp|(;~<*Y&qOj;^*YqW zV*dqG^lXqh8>w%jR!G9f4pA`MY`pyls+x7{w{wW)GuotXT9<{(RghZIBW>HPF%Ny4 z|`CJ=FyQ!(_q7FYfh6{}3TusUC%H z>wkQ7idvY=*)xxk5p$2!@(fULem0D_;%r$6)`!%T z9kkr^R!Ni5MO)Tc&UKHCKn;SJX=qxa(8>P_BY$IB8BT>rzLJ`}yrTUvDL|0s| z5Iz&#S2y`2BXF#wumKxAqTe1|v!G|Jw6dbR!oFZ83Yqgj z?V*)*)M0rPGB<+5ee+53*#{_bs|FA%tn+b|63?y>(&io3%ujP32h5eLSgV=^{bI#i zYfMgX=)5~(K})c^QH%{#tTisKwpB0sQ%>NFNPzU0eRqosFt+|7wBHXqFamq?>!8DS zuoxDiXRN>d@G|>8kLc%YPLO3Hmg>G^N{-(H{1@9-t#3&qdvuq#(a2n>j2r1TB`y=0 z^Ad#P{^XD21>}0+Ct+!WDjfLyeVh$sivP}Ww!d?izjK$rbC>^`+~x1Hx4;GceZKgA z$>D3ScDcA|E)GxdsaNJKov&nK#l{J|^l|d!$?fw0{E=_L5*bs7J<2T?*~|xJY49m$ zYl*2@a@rl_hnnpMO2Q5PjZ@=BMMy=?9m~Dem|BaBKmslQ&V$a=CSif-c$qeVD42HB{ zVOD{=ZBE^+w4#&y|8KFK4>G0-meLFNezt<2^^+ zHf_|ZY^RtFcy3|>J+GkFdG_NR7S!PzBLb$;QO%N4VghL9mPz!2dUOB zE$rGP4WST;SQhs2k~0>_5Kl!K1MS&%6z+^XaPL{wK8Ju|eK6J^kc~29brRKi0<2Lj znx2Pm-OhbN51D01yuMZfjF4bsFyHQs=+=JeIgLpf0dj6(_qgOS z5-g9|fx4ZKGqp+Z(Ww9we0M5^>vK#(Wt}NIifuQmF)OIVd_JP9H6OQaLr0v!^UtO_ zKry4N{K4n`BuDp^8qVP3(d_Frn1|8ZtJ*3qe{m~|eH|Mv`k3j4_TVX1`wyk^5}`^c zf5$*s1C?0Zjos|X4JO4V&n>6V21Ob%UBd}wNtgnvG4AdVO&kkN&)9$<#K@v z_>UiT@xyWfvR7pS)7K^A*|}Yn;f-$XD*O0+1)Wiu;@pg^bS&an@*anz@$pnZ;gDb1 z&Tx?dX0+MERuWx7SPT&8_y;b|>Rq;C8`8a*Lfz!l%&6JqREw+vjvR+acJ|*37g~Bh zT_MQg?VR_6X@PS94iOuFO7Sypyck&#El7+fXJK8&8%A~H=YI~|>+g(#}v@SUN83&YcC*>!EFD}Gw z0g~1A1U25M9m#$T9+H7cd_D&FT(v!2#teShZG;>lyAq<+zW|C|uKNgY_eFi13%9?# z^*BALxHqh^z;BWPfLO;HR8WwRiZN$Wy>y_A9$*dAsbcv6^ChW`h0+ObgK_ToIwFFb}= zP7Ls?-lx!xpJaL0pQB@6JR^CdE(*uas-CjQ5+lmvCLIN+<^v%&665a6#7II(^8&(d6Ie>Y1^wft(a%z2L(bq(@8CEgFA zjO`Dl9|}tO`#a>1|1CKjJxdWiXK0H`rDOP7D8~UE)gm@XsNVtkg4havEx8GKGtJ3L zfy2N0es4jEh7?=j$gGfWh8hotPby}O*R*1O`EUKb#GBhh(Gj&tGcJD*j=@b-8f zzDbKzB=|3`eguvlascriB+X&)1Q8JEeh8`{7Wjb&T*1=nr$1vQNh#uN z&{DbnuvgZmn?Xw``J`ql%MR!FLiL9=GG}XL`l0^_)Mh~Z&Dp5b+^WB){XZ<^(FNRo z+%c{-SPp!qN%;{%iBh8wPSU&{V0l554Wb@t20?4eT6TIUlMAiV z$>ic2aJq8R91pF6Q1vN6DY1eqcq#`on)|=`CbGYa*)t&4hXbdvIeF3v1C-}``+LV~ zWLUx0|wbNCEJ`Ze-y0>yIz_~MZkHxgPf~vu;8Ru$(0#|w57V5^p~^J-r|SI zw?=OC%rgK(cu%R`c>#Mhn%-aTuN568GLEp+GUsV51FY_Zvgt`VJS;lk7O21rPCT=z zS`k&FWuD`h3Jx#rq+I*dqRW(~r{&M;5(@ZurfFcin<}NR985ESnER)&+s@&sXM?Eq z9zn$@@0RC@uRK)IJm>_J737QGyND~kZ~U_wr261e&! zHAf06QVZV1y-Luwz?rK7p?@TlzArJ{3Iw2Z zhx64vJ;l4AH&IQI0(sj1dW$&g7$0fh7Yiod{AUgVsQr+6F`=a-Li#><)jp61bR-X%$y2S;n8wo)(=2537=a|HLs_*EuRrw zxd0F|jb_^bh91=n+a6m@DXjS7)Q3pDdDzp$!9F*0zlP@s7sAoB zdxYv6Ny^O)WiA6K=v+Sq(EnvOF^?tqUl?3ywLAl9?gbnj3;Zl=%nopUh6gcc(0lE2 zy7ytB_A{>Uur_R5Xi#Gbh&;J_8qIz7p4;{$-~h{?=`qM++huy67HB-fX!9?8ycf@_ zK?pHW5)8ukCy%#m5q?aZH&U& zA;<1J&2P++63nJf&@yA%&*hI@&|8^TP_lxrkNoBft0sY}XVLo_AfA~D>Cy+)&wh~& z7-xp*Y`QCnI)sqZocf;&+5*mRMc!=H}}Ug0e_}jdp3Y0+^&P=7?R*D1nuTIGR?JKR~Dkd zem`cOjCppI+p(;>;w0>yK}|Sd(a3oEzM&lJ-R2yxI>yv{Qq7J^k$5_ZXV2D`5! zk{Nf^a1^sRrn$oa#<;~RNdqwaMQ<8i&h!}#e}gPI+iwB~y^Rb%8=Y6|8m}t4z!2s$ z+L^#NhiauU_I`EqRu>i2n#&pJ%=m{S)q=Xj3+*K!#x#TEc#3rOeuiCdc?e{K*^VF| z>il{I{RY*DQ_Y^yQ$fcGNA+KKXy#Lr~ryPi3Ukw$#+}HD`cs? z6B5++N~X8NK;ij<3EBF8x=WoPyT<2SqMi4&&|KvJh0@Tp8T8gXV30j5b1*M1CQ+kk zezJ96iW7)i(|%`zop$0S@3y2EnjVt77I+XE4ZU`@>HASW1ILj)f0_lZnwVbez&eIVwrSt1XforU#p5wihk|*1IQNwHq4m7NKBpR3h~rm;85tl<#XY34?<_Jdps0t zpIKWJ1F#5ClxttBttrKSL?1{(K~DuxZtB$e{^p{JMj8qsP$FljY(KPg?kt&>xbiqc z^AFQalnZ3Ah@Ku4O(`rYq(%V_1bb#&-bWGnv_dO|dQz&Z12~Kh8c4vghELe3dC0IU zKyDx33O|@~53bGyd0UA(ShHXH=}Z6!l@+?+B)SX8Qi3bZb*(*0ME4Xwv#oZ z=a>)=_n@qhK73jby(motB>WiwdN>Hy)~B!A+8=N7hk{OL1y~Mzq8ju)Ow$8TNEBy* zA&hjPR1XC3sr$SEL_e@5-!`--l&F_P&p;L!n9zDaH{jlHwti5h;Uw-eno&gDn6DD~ ze`$y#Z3nz>t1jzEvd~XhNN<6dnmI8bY%E>BlT2OUE$nBDn=l}Dbh2hp4&=>pd4m@M zPb66TTz*#-ur||^7+uElMz`LJ&-wTUb%Ro5HWaTLYYEy&l4t1j0pkXmc#Ni}ngyO* zC77b&4!u86`=v{P9U6ZQeeMsx&B^30fpofShE4&nX5S13Zt6UzMv>8(#f`o?gGL~| z9(2yeRHlW!5wLBe-50(Wsfx^?IP%Fu#PRWC6GTbT(>R{Wf&yI#;LV_r$&o$ljpF5C zlcqehde2B@TSSh2M*?^Or8LGGXyZIlUT;DLutN|I-cpJYxEVO!3ix$$G+5fO*6AkEC)GCkb~AeI7aL;Asle%~Hm#hWxJ zKRF5F-QLbWmOFqY`#qPB=wgB&OEYd9?;jmzt%P*y403=iN{?58Hy`kd?1@y!Qdfap zli8+kp|m;EC>+b%>WgPKoa2w5f5^Duc<>muDhjAxAJjpEd8Y_{Z?Vy#)dDG9y zvs%)jV7j-V+bKW=Uvx#;x>~4ncV{ukiRTTeU&;>za-LVK9yOet-Ha~IOJmq6qwOLk z`X^y_lft;c$W3Ir3j-c9+AY-))N(R-BlMRdMtGzdvav31bo7W$TZ5K=2PEdtv<Zz+k0Yz^c8{yAsWh_R=`?Dc;v}}f`AW)p+gz8?v8pa!KUmdBVLky%PfOlU4&OpUy z3c7~C;)DtAF^R#ImH;`;V8eRqo(;H1wb9WxP7|d9Wx;F%CJ#D}?f_PH@XrO;AJ`mA zA zA-+AQfnU2llZ~fPL46n;RQW`evI0B+%C?^XuB`GJPmiiBAU~L)T4j-Vro|_nrC?r( z42Z=_W3inv7Kq&5{y7ugT`C-Wug_g;F!y<-gPX)KlpNqeWvUMpz&g@(7ze@1*B7)| zrHliA+S_HUcSkB%OrJ8sCf1?)Q$is_FrP*mccGa2PgS_j3?76Mp+_26qxXd8)O%Dj z>{I8vDC-0HGfWmhj^<$Eo1_s{uF>X33yw1ieC4KL2o?OA?@WuU510f%Jp!uvy^Pe? zU`D}-;ecfP3>N{?OiYs=bvX77x;2=$6`t$DOi)(BX8IARQJWqJ2L`gc0p5wKP|^s4 zCi~pPP(kH*p=hk5;>;;*O*gHgP8tra#PuIeI~yhCzicZ~pn^6vXftn=_eZC+z^y5NY0_iKl<-(tYuzfo#(S5d3DEandfz3f$la)I}`8nyHZ-sLa_vbEROHP5RIs zvBYHoQZ*?voy+S2rWrF6(~lT8D1GKnGMO$6AK)r_p+pxo!&M}if=rKsQ;+mqHVE>; z7a%DXp|3$O+CMEHuAP|rEF6!=)&f?WLGARDf%J(4ApHn6ogt+Eyoo>=%>Ohf8a86R zWg{1T@Q|M$1`GeG>3@|_%bmN2*BG0iHB9NLX^;(pGoVv?eJo?5uIo0jOWXLHxoeGA z14TK_P}EOsgzEb0U{8%02^A9v>MNf`0MigTb)M{<2=RqXO~C;%8QNl`&PiFJ@-zEv zLg!$ae0(5C8PdQG=oBcN*kBx(1))r-|7Y33f8JqTyeo6AKR@h&1zBFn z)fvb!Z9(fy)k!~xWe~-%23ij_&rn4fBqrDl*LW{^7%>9Xc8oynb1JYOR^lb?KgxKr zO>wfJI}~cocJ1lT%I&$~!-if`a1{E~3=At%;3z;lcFFe!&QM|nNP%zyw&rG+-vEgf zgs|06fI$7)c^^uw0A1OTb|~L`qoxbR4$#AIasvNK;@vtU=Eq)&t6qfZuGS7 zNlSAZR5XT86-{@1=5xEJYMw)HEEwS^$XutUuu9n^reYwu9s+wkpe*p!%@t5qc=Vzi z46e5E^J~xo)&QI}n;!T-qzKZ$!(egAn8Kod@G&iu(r9uezrNQ5$!&}86rL8+x=ixZeF^@s-kT245Bf*hiT!6$)y z;kVt&t$<0{qEhIO4ZJ%{$S9Sc;B_?6`vCBZ(~_>=cU_mz77k95CMAKi?2Eoc@P^0% zL^UW5hd%qP+iye#wZcAdSPqcrWi%5G^@C#B&_^MZ?Ha5UqaGWDODDJ0sfdT4YBoUr zofrU-Z+C*#`wR>nhJpGB#1zP8PKJX~p>=^$kw8H^K#*J-3Q8OhLOzKHjEJ5IA*g^e z6JzUOV39o>MS>hq9o2A&7_33k-SDJKjVFuQPxSuTRa-{581f{8js2tv`V_MW`A$ zn0N8Hjc*bG5;RC5rY7)S=vi|yV+DAx5NzksnWUR`cAW*aSHVSDeSr#s!7VKY{&PuF z0p>+oE&yi|*g%7dSxPpj-@W?qlqv1*4#DpYyh{3DAq(ihirvBsgAhC51AVb%&u7X$ zx-L*xf2qE^zgq45xh#Jl;kU?n-JGsO0k5nI1=KgN|&Ty#K# z(uyW#Z4(ZzLEm5JF$Wgf4~h~~>{w9_+wKH=7{);X1hKjMQ%114OJ4%6xUf)E-$Cd{ z(T~u9l4`&X#gx!evFJ9~#b{N*kh{2p8_mZ_WXvwIz0d@n^0xjUd~}0y5{u6!0Xv2X zYQ3``tE?{~%Wr>wkOImN>EONj!4Z9xlrj$w725e$|dRrLVpHp~4$sqkFNIhy^?N0l@=6f&eE=vXOQWSkU_U9yEd zwcJWAB2-nZ$wHn0FJ-uQR2Ia|RWVJXVa)iVDvl%?yfZA&vhUuIiUet z90txg3%upQ_KXg<$HLYlULrW`3QR@$0Lm0@oxB+GABB~rb8j_ZX_*6#b@#Am2ZJO} zlx%|<pK%}9t&wUt+!zz z7_C1Lc)R;~K1Y?4n*67+6x5G<1Y;zNjWVV?sT-6qt5%}^xm~iCFmuz7m#cYJ zNp;|C^)99++^6oD;N{agaPmArKGQtPJLP9r?Yz4BG2`(Mvi;t)%#|qhzaVk8N?0(B zTxA(}V3iOrP{aT8K&G8ec;xmhofvjc{#K|_<=uP_wxt4OVQO)>*nX>0`K~0(MG_7- z$S4nYFD>G-9Fw$Zu>|~KhSKY$5>u$c!0Bu0&c?-1M4H!=b;rUAHKPVgcv{6KUc=Qe&_|p}e%%i{35XDt-svA4{G>*V^FL#_GSfPV~42625#gHIiwX=G_|>(+oH;XeDU z6~8~Rr1e8ob*Y1+msN@yxLEmeCu|C$=DXp^-F)8 z9q@SX$FIzn|FQ6h^ZvcT-_0_*^|2(t;*Z&PR;<~~(ERC+#(?;zr)k0c6@F5?rWQg* zo{6wkf~8;|KC>H~c<$=Q7`kIGSEvc=dGeH=q(Hi2bOM>&O7TvJs1aM=bRWYg=-+XT z@ItsoQ#Vgu)^j45P6?DI)@1wky7sPL&?}1l1(|i`(QzC_)YT&%8ykzZ3ihCgL_P4} zah0F3GDicPRPp;r7I6JANly*@*u)aAU${xPw8r{Xg+h6c_(C_uc)SYBOD}hv=o*WL z7fA-K=>gJ95_iy}MBa>Ex(s%Wtkr8ajF8C&y1KgX_gT*(x$2!j84r=A8i#m?`)QC?&fvZt(jZcRuYzTCDZJXP zYQz)`3JWug_;x|)UiuR5&jP&MK_M)qi098{v@{9vO}IzY35~cwS-3V%v|y4Y_mh;v z$6-skKXa3^83scfL{@(^I!RQnz=lvn6JyrJIBD-ke+QX#BHXjx5hN6_#u99DHf&w5 zS+DUa$_0H;pa_rvt~z?OTqeX=o|y1WV2^5f%}vGbiLtC-3nvM@B-?*#)}i;&?}Of8 zd(LMw$kMW&*c`+B5^~B1;x_WqgwRIZW*0mVL{=}>A_u)s{9P-cyIMSx*7cv&>lR| zT^3QUSSQTcpvZgHq-du)28dNo$@t4%7c(@)W>qT<4WEs@$+DZU{%=Moog)D za=wv7=18zsq8cbyhFO=*R2!h9I6$i6Wv(T6ffm%E9xoW{v|-<3zQoik`tA-I2qttkp5HG3bKaUGuqQ1jX zXB%3^kFJSwgdlb3Gw5Yd7{P+TA`Gvm2Pz7{KFq`nKrlW^y&sRjVx*w*4BKh^8B3tP z+I@i{8l3=3H(2P7&)f{~fgI!rLfQi%tYr0XS_<6z zU*GH%@L0eIO-OW!L_Q z9v5)?3o(Gcv6SE*;GZSsP(c=U_cILumkP&;M-4hhEjyvR{%>X)d_M5)YF@?Vp^)m@ z=g(xeOgg^f70B(2Z}!XZ<(y}q`PpL~XcKv7hbloG+K_-{UItuJ;@-~w@phUvK{ddp z8U4FSa6lj4kt`pxjY1xy<7Bp=U8t{gOr@HkHoqKX4o9X#&NA?a?G%9tAee^}iscWv zf*}TE#Th+{AT_lbiRJ3Q=s?F9S4;V0;aCc0XdFEsG;e&3{i$VRgv|MSkX$6a40h-| zdy4Xnm`k9`6ixJvIe``@ffu_|^s*VP`2zN9@A}IAxem)F zLqLtwU-Sh%U;*lq$TL~m0=$_v?0d`yF6L5f*kp78viLdZ>uJ|AGv;8%}zehbUJS@kX|JeU<&!Q-@MoznxN@WCr?X$`I1WD zuL&k(t{|MS8rp?}GH$@>Qebcxkj_X@F(?7vnl57XmuCT0o%9|?fQ#P(Ct(C~4w+`9 ziG*5Ox{9Hgn1J$c1DwRZpA*GsSpJ2KUV@mx#g_;32Jjq3_ry`q_E*Kg#F-HFIpr;X z1+r@lp_ zHyB|u{HAh1%3CaL)nDj7^^F!M3b(Wx&k4CGh0YWfUzep8^a=3_x@Cf*|2r}8Wf})U z_%g&zFs2auK_d(VkxK=8wf`+Q$jJ4 zLx1_X86EgnPT{UtTFz0+p$?SxWP#{or!GOE|H2gU+Z}`XGN)_|zmcGb?nbLascR?q zUkv)2s8SI+;Q~jB>0{C1Jq2L;e>w2?6me&bBA2?6p%|!il=H(K<=j{#6iELCCBe8c ztz{HhPt8rr=)jo98_fS;@4LgAJiq><)`?2hDk@7{R6(esh8-36fI2D4Z~;!j6v9Zb zR#A~9D#b9Y3l$Ls6_61GA*_H3h^#~j5LpQ!KoYWk=LuSE6$SiW@Adn>Z~6yUF+6$h zamMF-&biM`=OM)=4SmSWx^4x+UN)L0DQ7E0dG}mXAP2#BYrP2~IEov;B9-A8J?c{= zd>Ro}C0T34_%msUrpWoe$K>`WM2$H-_=_A88kEU#^H`;cIK+NTLA^)l#XSNFgY3w8 z7f!&!2D~{xRd;p=;%+_y7QkL+L2ajcKQEDf?plKtm(m=?WHOEa(?{J~Di|lBLP1ET z?{Slv+N;Q-x$HcE`ADp_vwpbsrJ|TQb_k9bDNdgU3PgIAsTL9jcI#s-2|yyvn`QL= z^UTjahjeQ&F}Ro;FacZ4xT|UF^^4B z6}QpV2^~EOG;tjdnBdH#Aa;E{0&uI2C@(LM71r@8L%Av=BjkgkVPZ9>z*2x^S8TXB z%fHv29|{4CuqgV{pHkfDcUggKCT{Jz%h@EwkL~7&Zh_%joznE#Qp4s~?~TEww+ML% zOwHWX_lOX*+v;=^$E1aNisau28&nSi&i>_O-@}n2axT$cVzQM*>XE}r(M|GbPzNM3 zF4(kYiXdP`)QYIGnE(m)8!uRhkP(t4x9uf=0&~%jNJm)lq}_dw9t0%^@OL#ih}6so z5>OH)`;m$djBnp#GU_HK1*#It$?)guQh@C66ih0(jR5D;5C|@VV}jKm8NN z)SjD2NI;Ch*QNl=8b-q@IRXgpu#YBn@mgpGNO86!+%-W(D2ofkK+Rr_yS)lfTfX70Tf27-ZOSSQ}nG|H>!E0h8xYZ%M?-d^}ps=yO8qw3G!I(EiRq{qi zVQ=CZPVr3)QHRhBtqgb*ar9gK0d$?`KYVuN0qxchKR&F$0R#)$OTEKIkNxn+2nVyE zW2p9q#?pyMRNJ9oCdn;}PR}PH1!Q9pnl4f5$JQHurnCED79DhLiPu&$YR`*y@-#5z z-s2FWt=IX_QTc2jiC~%dm1|fe4u#y*NO7kM+7-y!V0TA-bzm{q z_DC8$iS@x}hp7L{>>^gxmo#1~%m1>U2)uq1-@B>*d{wbExQ=MyNgE{sXu|b$KwP%U@T@RerX`PTG1@!eH0z4J|3#r@^YnO_OB6vfQ=;Y z;3y&CX66}jcWN(AjBg*O`Gz|rv88Yom}CJb(vpLG4_I0E3(__80YXrT~QRRQK+kq7Pm z;M0yPzO=D8^CkPKYE+EI3Of+@5&%1#``$f{t_cg67%C6QsZaQ{P@8ge_*b`T6;|XXt`aUZx6y^#O4VMPDZ+e6FvEZ5DR~z%wjWa2Ovq z8u(;kt^7Hfie%X6e*iL&;lgNR!|}SpNxG=}SKeENol`(3q^QNT3M=*}KV{z~2zaV% z|H0mW!tk{0dGp&esTy$$fFtUAbjIH7x*WRdan4dZ&8vf=;{kpHM zE@G?g5k-1$(7y;n#sWqDW+SXP!j42jnDj-EiMWV}GqA=V{Kyv}mUM_ngaPD|`_gX3 zFT%o8z@#|N1?50!oh?EpIv3*OPS}L6|Fu+=A{ILy0jA|zjq7I)xCByW(HT6k0oK@? z5k@W_1-Fq97h0r2ju!7(p!dS*ikd`VaR88j;`_uhUzV|-SL@817xoxZ52N{&~ zeQCIcIC_P3Mpv^s62 zd7oH|K3wmy*I4|LVl;t@#q)WIW(Z*S{KQQ5HAO!_;qmT7KUSItn}bEPJIO{==ZDbB zMhh^Gy)2(v$-W`Finy1J!^n+5GJOF)gRR2&q*K!bJtTv!SIIO(vD`MuosB?sKEqsj z`5p&cSPRVA7oaZC%I-j))1wpl1$a(=tc`?Ig4(_LJvs6Sm^Q$cQs1x=qUA3@OeE3e z6@jH1;X5uuet}GK25S3Kj_Qx4ic-)tRrfjtxVb)_^aL)P&Y`Q@R6?4n2Fn|EZphuh z55f!vln5UA3)l}Fk`T$TA|b#NKwtE78&46r4wadO2nY~>2H<2n-7&x5y?T>+eONgd zJf7Fy-Y%k(2@hy#J(bz&u==~Ve^9!kC(|_Km0HnT-t^%`SultkHr*az1u&Pf2!@fW zv_?IQyO43Qwr~FnuN5Ot3Khk0rfC3=^4TYPI9R+G95O>;*l)^U%cVGTml~L53*-3K zKAk3gJtr5U#Eb-R=gskHIO$FSAdzm=jy&)Nmr68J`}FBKNMMT5$1h@{NghHnvgbol zg@2o|Z_k-8B1bkdY{VX~vBrchx}P7!wnH)jg7@xO^%z9JJ8-srI!t3+%|WWLgQU~N z0J6YcmB0@u$q-IM-Sz(yDpUOXVdl8UjYF6558_vtOC*DH}vNzo|6ltMLe(&IdnpB zGZ`^7z41qg`!@sy(50ccA}d-n(vj-br9ed-npE!~m!9|yi3dfYlSv&pKw14ZSql5= zZ}4id5fJ{gSbSY&D{&-#Jv-jp6T*ZYIq##Y)-$c@z71f}uMh9&L#~fVN@#|XHHyPB z^+7IYnf1mB`TI!gAjJ4sQF092C68xrYyegy7O^5Q8{jC{&khpJh2Y|2QADK&BwXn> z9(3TUG!adQA{K;*3^DAb|38wNZ$*v%W*MEjr4ZWi%#1zRVzeqj1a1O5!WVKwA0pp5 z=gHEn$VYZjGmVz!Vf0)$%vcw%^X-?U@4M*bckKmL(8-HK-T&pE4)>pY>q#y#n#8$5zR?JdPtsbefZ3Zq|d%=O|WU4MQ zpFW}h1jcwWBIN^Bhh`!X*L%5H5%uhgsPZYWCte>1jAVemfN%aW0)(FZB7-^=eD?ta zcDxs?K6pw1(T*7y@lzg=F0sO?sCQJphepADFjS9d-W^Mz7Gn(Rp&hAIFU0E`bIQka z_(4=3MgUn7%(L<2^2VW_hl@-ZE1BCr5W?I-0 zYL0=z8+IYE)?JA)gy|zuJqfg?h`bN>63Iw^A!~vp9GbG*88q*nW_20{zNi6RiACLg z+TR6KO~L8ng*`!OI6CAKqK(8CA)`FRH@BZ_nBjp`(a`DY+9Xl4x^|!{MohjHbx9d@ zpkHbQQrBQ0pH1*>W}9W>crRL1#hp&CaXsi*)Rl#T$l^0KADG!M+oIlV&MAU@a~R|* zvfc5#7yhht@r#k<_+iWJyA2{IrF_Fofg!a?(_=1XWkekn*B`7H;#=IGsROvNmgu3) zOepax6%pzfL;Pga&cuFf7?S3yivyVlJcQ$O$e8ZN_H^w)n;(2%_2<11JX_vDoX zV_>hfsm8B}Xk$bCaMa~~y?rl?5lGY+Jvz$OtMh_Bz#>tTt?iZpbjiI3p;h5XmJR|3VBpU;%&>OeX)+ zO{nsI!%J12N;2xLIR5sV)SWZO$Sp$wi6q$MKPg zgE*&!b`!Ba+59fHyYb0S6ZwBnXXW_c_6!;IQKsBq;yKz%++2>>{(bSlKN3_@F`1;d z`{eK$-xgq`w9Z?}elEQ1x8op>Ad4EBsBg<-Vl$r8wlA9RH<$-sJtz^HfPmi31bH*9 z_nkb&_uKMT31#sTo(O=^0Ed~54Aa|NhzGnkfcIIr!37Wg^Dr2^0U#Q%L;v2mzUYf7dC1Zd?MOT#5DcSF)&&JbF^fdm!rtq?69SsxlB$xZysn3F5<5 zftnp3C?&+=0?`)!uaW~WQ@(Rvvs@vRo4IBR&i*}@hj^ia5#zgwKooqe-GNvwb7JeX zEPQFTRINef&T23s7dzgk6#=CBc*;XM;F2HVOFz|Rq%Q8up%M&12eN5Np9n5+x<0--G%_P=u||B2PUFiwfqbBfbK zXL-Y>_K~{%@{1CLfNc77_#5uqj{;)p6Z;B0;#UbQ5Z6>tT_QsLr>}BY z+p#6$A?iNuda^U9@55z%(88ecyA=SSi*D)>E5Jyet_iNcp?h%1ZqhoZ2CxzbkM~89 zwxTn&04fVMx%Aqi6t(;fPA`XMB4`qD%FCgBQR1($zE)DJ(RjoaqFzlhE72NsxmJI3^paN zj|2ipR%;eMCXu$-o`bmK5XJLpKdCQ30YJPL0Ul&Qa37pK;HB3mMW*(ogT;+q083_~ zXXECX?u3HSEtY!Uk^wo0xbV=$w#8}Y$d%u_kpQ}M0dy(U-7^GJyY@KHj}}Y6B7h%W z&WUass{|%Jo<1~KcZenK&2GS|u&;?n`XNaSOzAXT@E+D=5L~-g{SsVcTMZ@Q#hFe( zEbD8*8YlLDjrk?6BLaa{u5bd$4R`CeNrL~#w-xTh;q08VkFjyJWfBNQSW96 zdunIZ?>+rwSu^oEg$z-v`szwh8l9Gcuj&ip;`E3g*Y)@bk=><|#7R(G53cS$O*rje z^@&pTMBHrz<>NcSBEmb7qK0pZ0b;{I>V@|DP(i*UuSFMe)JOob9zhwGC|}c@ko?pqdoX2sl&OtkJWa@3-CL-$Is1 zyWZ>UUM$3NM5m7L16$Qcg6N;p`N@M)b@-+i`KS}%Af?`J6Dj0 z1p}7~t!MZc9mmD)4G31lhhC*4;3ak+B=a9+U^%ptX96TAKG?8 z?g0(pD8)(-fB~4^0qqgQ8Y2Q5??nK38kk_bSpo6Qur)5`#eksx-d1mF34ZT|$UFoJ ze?t!}^DZi&IzH&$NlZv3_QK?j;%SJp`oBF`#9Zy|!Qb z`v1csf1q~OlLsKv2=ba2PlizDnx-RY1suW#Rs7c}wmqbO$*`C?vKSjAIhh>V;W-w< zk%FP>iv$5Hqq4rlfqp8-gk^Jv;|hAf`xGF;_%&L?QO(>Mm3R1q+pC|~f`nRfP+{{m zYU0y@!lner+(n`tO~Aolr56;O8;1L)eZaxXqZ06-B?-$0q$;wB$#x8m1HC`_`A?mZ ziK1wPOvlvBJ{;HuqWDv@2)X$Gf32dy2hf8reJKG+*&NsS185H^E*uUNTi+G3_i1ld zO!*BpGtYpCNdOd?IXNqHVav<@c}6)+)P(v-imC+=h;PR1dGluj2j4yETI;F({h(`; zVNEVB2xcJ1N9Q=6loF8)&3-Y&3R#&C5{7qtSX+ogk?`8$%}P5`NZwY!;jjXqp1jS* zpOAyIW|c#6A6E4}{rGjP@r&c#BgYLttS3UvA{(d+fPZ$!PraGYPmcj3OF30{$Kz#D zn1q6E;`{i2hE{Nr7{N8tQ2tv1uOmp9#;zG9sus3_O+iS3goU&UsJ~M~swC$2D?t7@ z*4|=N;<|pt@}KV7NvPhj+tM%EK?}su7CImHo^*nKHf8;b5I@1%qBuV8IC82S>S6+nW=_);w|*<#_Rr@g3Mkk6#o}0kK`EG$$LT$~`wXvhyMIys zCmM%TI&JJHmGX%SAr)AmgIE&T)WAv0cI{sbDB=PZ5xHih7NLkuSh+-Mr3WHn<|?{N zOE|O#lE%Lu*QiGlceO}9t-o4R5;F$U`v3#KOaZ(DS%*)o2Z$kRGdk}eM7i^ z+1m?c$LxUs0pYMA3qQ=BpfG=GBS|TceZo)vtHyp8M}lWp^@Lv7VLl4#1$dC;4R7E~)%~gC zf>&f7k?{?SH>)>Li2o4+g?7kKKtBAxXM>^GjldnoNFqy?)vUvbAw&tUANbUR;qW(+ zQTb#}$6!_sO8R#ttsIn)Xhz$&T*@1iPBd_i)J`0fgd})J#qF9oD20IXnL+A56yiU2 zI5Q}1urMxpwIF0r%Ksj7Ao(_=jc5Nf7{MI0;9ksulsF-+Pt8CFk0|4I`hVT%oD;2P zqi4e-(e6l<#fO&~?phP|YUbDNBm!5)L;QJ0(OOs7bk~(cmYJOAN7Tdw8n3XbVt1GH`Ha*Up79B!ZVG$ zrciA>uOVJFgVV%r88_&!3x{vXUHDvy)Lt(j$4l~|wUaoD5AXw;IP(}Sg~zucjiss-RfTm8h1$kAZWq>r#nWI&`xp&o38zPs zB%Xiri(3dMnt6}1?Sn|2joLxcKApToKa8l=6`DL&cTaOi(sX1SdgvsE{r*+ zF~}x^%aeEstKOa<+w^b<$C|s$XhwKveQB4bpT!92SkFO@99&Q5Nb#F}OJ3>Dz7Nga zW>es(pu91G4_9ea(xcDnv@U@L*Jj(&d*TMa^#MsL8Jr&4nI5>9qLggI=V0(I!b@z0 z;(r)36{J(ZLwBkaI(@@zFEQ315gw0prlfDBV;ndfvdy~=^{G0870x*Lt{};ivLra3 z+nqzlLPNX!%0Ua$s|slJuS$4(0$S&I3KN~Fx_IxUgWi%ZxTM59h}2#R-_}E=Yx^7% z*6$y*;Itfu9-HuO<(N2L7h$;&I?kBpe(F;OvJH{Po~)1@WJBk1cN54HAc*{K@IZ`A9B42Gz6H8Gc{i;AZ7au2WGw!!#cHwP z!LhR*o7;OyDI+_I8xhEDd(sf;#Cwp{KfAn%g;s^@Qu0Xx45eG5E7s;Fip}BZg96T8 zKvR)tal~N|@kLPtW=hB}iR5fSn&br=^P_uHnxu*?IbvM+>STvFn=DD>-<61wGkefA zJHHY9!HA{3mO{W%QY#T)l;MXq@_*W@b4q%GkYBL~?J9O(lb=}7al~pbVhCrMSS~shHuR8`C1C;!Nhlp1=bx4+!Up^T;aTI47TSvj|HFujV}$WR=j|^xR6cozc$3vp3Co~WDnGVE97jK3 z21B##Ca%zdZUGn)&zx-LkcD@d_01jWa99fmUSPeXeOKYjUSp?p3h|sG0-+gtTcP=N zoFm<|M`Dr^oHnbEY$Fg1(_kf`0Sj&^3xh*`DN#kXg@J@CH#lO&-fiGQ|L(O^LOqYL zG`cHZ85S9#HQPdV_qi8O%y)7^9;6|Lrym7Y`@^j8gbhhz1{_1=~@eh{0 zLMWQ>03xAYbU-+DN3wPGBuVgQv2ZUUCx7>weT_Zj19vL1kvo+zOS_n{Hn{Ihg9aOjdx$643WuGukz|=m{OcIsVdtQ$Sr1QxrHsKfB$5d}%?4nB z$#58i1~;IJK*u1J%2VvH9!4&~*S%(SPVN|p|L*F7COc%p@#eR1`BR24-pmLNq1L;$ zqV1uy?>HQ$Sbb=rBahVyZLjVHQ=n+i&aJ3l0O=LnTotCRLTHM^h~&0nJcSlvlAfOg z6h2au889(Ltr9yIdJYZjOLG}uroDnVMPV3W13S#vtA$-b6}EH2v@s&Sy9z;=8!b5) z0o{NjC`fwyXE>Gw*)=#;Hm1^h$PDZba{uganwa4r&WaBtb^DVsY`d}sjB(c(;M%@x z=mzA)I-Wg2raqmGY>oKz$^#jDNP3Y-vHoT_1O=owoJ5Tl3;?vWj#v@3f_3AS< zNYD*u;LP(H#Rnh|Mx6~XCMd?OQotW8n_L;8?3-H4XSVRnHf4@V^lB(cbwHJd+|3& z{15Kx|JYJz@H5$o(YoCx$4;hYx_i#XvL=NiZrZkA0D1Sb-etpFxeBavuXNtf90**i zgdUUE)6MoHpyWcszA@BIbTtCss>6_#vo97J#b_nIki6eShu1-if~BU6m)$fM5NOA z0a#CE+%RJQ!;kt$$!cgQ+gO31=`EMwLB-eo2jjEjbH=4Wh0J7W2$28}QZo^v_G^i| zkEUWKZh=D{)T;C%tqTpGFuY%>Bl$b*%0KL6;sAAW(kSAFCQ!rZ`~43>)>`{3Izxeu zhBS1tg$L7)BjoMZ^U)t%*~*TcHNjAnWTl1#67vc_VSW2dyM44CvMrZwxlGHyS~DWk z@_16_{yj)1GAC6J*9x?%-cF}+g#8AT?3^RNdq>mj}y}J z;ItH!B;6RWGmO*Jc7}6LP?I!oz`hK~OeHwM^nYZ!1sG{x68D^o4bTk|;%$@Sob6{zG={Apy>ha zhm6j_+IvKR4}=dc`1u(cx9n^jOzdJ##fqEUBjJi%i5s+J(7A0pm_Wd_K{VGHYWFuD z8teqbP`w{swrFqx)MlhwXplpP#)3SJKOnPQIJn4hH5+R9Dc3IzE_e&5gOVcRx&@p; z#ZQVk$U%+J!R>r2`YdS$oKk?0odF?x&$+=*Ay`8)Y(CnjDK5-Ce%9fEN0Gfd@X`~Q zzy##b!~mmjmsBt` z_W9-H$cd%*=t}0>WvHg#*%XPolAAlVS=MV_4YauA0ADn>ecn$gGLA|{4NA)$`&n8e^X!9X z=RV=IaW+R3^>8@agD_}k zKR~(-x`?JUZ9Q$+6p@z3dc9%51y)ES(VEVAE2CUZt*P#2Dj0zaOnAIrkTFF zHp`&<<$w$8kS4KcpD`iok)dH+Wv`|ISC~Pw*kGdZ$-L0w{6axsy6b?e>!4|D-lpgk z_3Ie*4L)RR{Q*}N%ESQ9c*?{;CI;Ur29+frZt{kDakS)h& z%K?47Kb(1%^CtJ0{q?=7lb#@Ij8>Ak3viNdc52;F+5_>{TQXf*6n$xGx6HJdeR?&6 zY&m4h(f1KtnRLjcLna-D{X6(2Qx=)B$dpB8JMa}o#x%V|zCKS*!wJ2uJDUnPlWI_SAL;mwhESXTqghD11ecu=%b00GI(XIHe zCgC!n_}?fLT%?F`m)gIAG3YO~xC1W7?N75NJIrx;BT3wkeB`RKkL5(rU28fHE-~#- ztE$B4Ous0}j?>6ZY0#JCLqQR=$qh(@yLS82sH@WKjY$bXVj#AH!qhDuxjB?S1{~ zS0)(k{f>`4nTOnxH~a7UGNese9DX1jsrk?T zG%lmyhpKvtWnzI;)yu>pPcBU}+-$>G!AG$W$6<9z#^P7@4~zc68c0=ELh$02l<7`t z!wFwGlshypm@&iR(C_&XKQ3Fgd0X3sYokZqni;-(Xu;FS)4{&=4q0+DX4kq}*WWQq zigQ@USbKBM%{c_jQ_k+^zJ!D_W1mj)u!~bmHm*rKJq>;uT1{ZjC7M(v-kqRs(TQFB ztn^2-?JLvHh1eGTHAh}VY{>t)vvud5ghiq&JCA$JuRFM?F2J0u;%2C$%yxaIce>9Z6?OEym zXNvKGM$OXsoJRk8hF#?P%>Pg1XX)e#*aW@nMupRz&aaZJHZdH>-nQyl;Z%!UrJWtm zNfuG(R+QYEJXfPs{?6pnF*Bp)&Z2s_wQeRO^I4O2eEm85o3pH+AwQ$;o%RT&sI^(V zIvuLngPvY@@N~@lnbx^^iyEJw_Y+e(_W$I0EbbSJaQv@v%M2&87f)m7#_kK!N9Lnn zH*VWrWbtR(Nw;9tGvbl)2TKxGN9=z=dhw%~iQ)DM>_w|DE%du&*onQQe(ibU;gk6V zohJ?rue*IZCjT_rTG^{iI-d#HD-)5$S6C?B0*#r}{Vr?0E-k5>?Jo{ENIxq>uZ6?d;&dWA|(?kP!X9($*h#j zO356b%<;*vlnhJBu#^m*%iy^z;*&*uG7>>XBFIPt880Q{rDRm6jOvuJ=Q8$O#-7U( zGO~n>EXOCy@yXK0vb3?R5|+; z!3h!?I<+bGps8x#S?t1B7kh^>$BBq~ zTpZugPMdsZy$h$S*iz8g+{U^rrWAkoayhHUmN)O+<+EI3$NJtC^G**fjqV`ypuPOc zzORm|vBiiakd%@t4X%G@8I@$bh?xG}OU`;O8_H*eSDgQKt73|mG?MOwjYlE>{ZvoN zy6&^BoOOf133^T%g8bWVC#V)2D}wtD;J+zQ5SO*lP15_@ea%j+Sh)u+{b={79yCZ^ z?YI|*oS^4pS*g~CzNzqxW!OsPoy?NLOUUv%%+Eq+1bdot6A zH!Iq8dcSjS588$`zw^jUd)2r0(tkp2>cnPH$&VWreEgc;F)yopKN8f1fcMjo{nNl# zV)y;9wr(??^Fiy!#DY>UkL1NAW?Ho_9uI#lZ%najmP>X`5FCxN&N3;=_48`NJA~;! zPD}BSudZl!oOb7Ug2D4>o9$IL)$Ipv8kc!=m)K>k@{qGpf6UBDjTQvn%JHHZCo4NK zvF)twhO58IJ8+@riMJvof&6sV{rQXJcf zPrOr<_PC|f)BWvLy|BXhWjWoAn%8$(EpY!`*l3d-+wQ1_UwbRhjra6?nx&s(Y&pNA zJ$?ACtvM=LW?^q}%6sE>v@|?&G-i@cI>xdJ^_{hWGym$E%109q+`#0>y_A%?ag1NxFr=&IWg73rEiaWRF0c}CK1=|G27b9QJCx=e@9oO zm$bhV`^&ks2U-sZoVh-?BSS0OvW%>or(JSMExR^r&*Pef+Tn?!U4_=Xr_O1#ll!Tx z_BOtO{FyE2w=o;qJtwcgnadreuxw{oj}yAs1k zO}H!~+T>sAIr?}~ebR=}&(FD&4r`v}#I(0nZmw%fJ6YMW&%+R{W=&UST4zk#u=58F zyTdBVr$Ui;jK*+ptei2PeO`gFIiq|LdEJ$VOoPYi)-c#LrMf;$5Dt}Vlg1dxCTgr>G6K3JyrDjTmpf$h9^$D#h(AF#BPNt>ega?RFXLLQTS5F5xEB8O%~5mhlzGd z>?+1ZH|@F-LHqS!TK1BWm&y-C+5b9^9g!RU*hOjgie01^Z+Me4Dt{rpyw8uy-XOL12m!l7&f)Qz_>D}|X|EGjo)WvL z()qQC+g7Qg&8iDZ4ownG#{WWyJ4}0K#cLXx7w%&pR2@XBrinF4!%qqX^LI5?w$Zx} z(n~1>np_Na+hzLo_%c#0HYvy*e|1r|vJ>ILZTiv7p30476JCzbOqDcp3n`m)E4%jw z29!AtT{b6xJC`QNz`dsWX$Uj?qKnQ>!D1Ehh9%-n%JK08m!;(HUAjKkUNULCNvE|{ zEJt%%;86yxjD3E@8bKBM1x^rmzHKKrPE1k7#ix3D9z#C~UB}G7YdZ5L;e_>`1DAYo zP9jC~7uJ5KI!?)$GtbS`2?=vT= zI-o>TREk!eR*$!y&N9hJGT1HA!txXKDVN0KdUzWgi=*p#nRPvA_gFV0YEP`=C6_VF zCTnM0Eww4uPi5jTDd$a?H`Yt+cGP>Y@3PkF)o318J<-w}U6Jl^yEM#&Sr_W>lET`v z_6c*BdGRSsd1p`DzK9DZd4huSutzS{3w#)L-RUjTE#-}Jf5|pAK&h&;jr?sB7Nwq8 ztSTNq(~37rF9~5*fO}V1hW+0x0@tl zNG?tyVp9E;J7o_xJXzgfq<3~cHc>9kw;=rp`sLUw1ReE7>#Sd{LQhFqX}eq%(@=2r z-6Jn2_9Y$H0=<|QUMDQC=&^KktgiYuk4rN$Er{HD&AKLWm#du-Dy1mbXX9^VsqqM| zBy$g)Xnlt=Bv;=cX_VKDf4SDseRkX|>qY!9j?k`Rc-Wb%hfQvah-h?#amho%EHlBK zs>T{gSOqD>o!P?laE@whx?56oA^Qm$i&uRZy9s^#&+0Sb&i=$y?mdr}foDy_&NtB_ zsP#>>D+)ys-xIxDIb_!TLWA0;o6x4zceJ9wSRcEdgBScTujo5#oOPy%~jlOW0+D|vd-fd#qDjan57#67}k#rZ1$C4FW`2@Y0ZxE z>VaL_mVK?o%RM)ATDB!7t|YcDf6c2dF7`T3KWX1$`3zR=bE58rMJBx zEsrK|uo;fxv zx3QOIJgQYJiL_pvDyCFFQIAsGR6=d6BH?!VJ;*W=HFRO40z8-(0zy+F+b&h*w6JK& zZ(WYCMX*Gd!Hdl(Cq%>d)&^CQ9?^ij&%8H>_l}vGC~QJ)m%#FF#S6!@Y93T< z=(2^K*z4yb`Q&r&tSz@^TrtaJ*F4)iM!yHGL#JvfxSH66)=bB4j@ufp&NSX#t&qUU zkY9G!X!Ioo#|fO^SGx09txX5Rov#(NcNHml!CP899xEQQNeho&QKM`&etF8S;OC@y zI}M_|qW`Qd_dc5;4zOez)0#}y7*?{HCzf@^G`fvCD;{@B|CBhOCi9R3SFBh-D4@U8 ziuR17Za1x0>FC5ZuA=@L_9SshQCfG?%;=M;Puf*!_ubNyISnX%P?Q-o)da_Q}#TxD)Ui9r5cFL)aI!mHyH+2#hSC(tyyte+1GL$b;e;(+E;Y3 z&hf7)^qU=rQ1ii zimc}E;(*pV|1|Grev;~Kt*}?a9aUQ zIjXF+?gi=TuWO!@oY32>YD7LQ+)DsuZ){R)xP1TDcFlA`;!Z2AL)ESqYtLBTdf=XN zMgG9q{AuG0Qw)j%F?J22-(EeRx#0G#DzC5=*a_ouK?u1&jkX!NsO2(av=h0O6f%iy zC)7I_$*x&`IkLqf`er3qF~8|rMhF0Uq#x-rx_RhB0h-pJHQy^h$azspa=O?Zfw{8m z48yExl0u^5&Udukw;H(E`riX9$CJiPdz?mWpaj+~KVI9=4u~*M*?%u{@5LLz2lr(+ zwU#_!);}4tp{Kn)oovz7> z9aD8-<+OO_kceV$`PS3w+zE2-b1ZjDRy*9AOl0FOGnyNjiJESUZf~%ewTo z@oG^e@yo6ePW&~6Mhfv)G7Vc=*yE^OU7V9uJS4a}i+QJfcsDi*O(Y*}VAyfzCSLKn z^~Y9oGY1ukQ1se3FCXh-?0R?C{(Z0cuk#L)i_6bzMc?5mGriL*k7#j^maR$?!8p0& zK=1d!#8;B^Y=%%_VeF3-r{vHkubh?dPBU!o$`mLcO6N}T{n-CU2(kV&lJg~<3(ahEOA+J&%QVM^mOYd6YVNi8HKZ# z-#TXKKI#yLZnIl5xBF*%KML29vcr%@x~+Yf5c-#EMF4SHB4HNe+8uhak}KIO)Pgqu z;S_DV9oG>N-N2&diBis?qf@F2yb6y5jdyjz&hN6FC--ylCUN$71t+=jY9b;Jf6BSE zY&g}}TMT-Xf@0Q_1;jMR@;50F)V&QxDN9Pbyz0sKinFd&9?S`i$`qH!=8b-< zlkSsTNebbfcDzV4bj$U+G^C-rn}wzAG>ojEyl4W!Jqi1#g5wxHaycCrt8&Tp9Hdi>&bZ)(q52UbhUmUnl1B+fRgD%WOLa4Is$r#3FjswjK_<2w-%KlS20 z=b*;W2BsJD$hC0l>nneiKMPh~=wt6*SoCnK_d}85!R*RJMn_jSR!Dqi89(80u1j=r z{h>?COgmiWP&Q&#WgGc;$z9;YG*&fYk&y;Ipm3B9UL$bS7`KZAt)+n;%(fXB(SLZQ zJsB_G=nDpar?aHdA~&Wo>Y_nJVakQAL-sFYCft{=ypzA=i9g?W@w|rfLsr?%@XuGs zBUde8WoOrJtiS8Vy&A46LMI!bHTUg4xMX2{?#`yogd|Gw!xF+>k>WH%d&2O21j%Yo zC6}XqXnMZhEoD=Np7}AeS|)9AwK(x5p6L*=ajALA)k9JIbKr4YbV$x5WwXaQJOiwA zdgr-gM&L;gJrxnJ9i;J2nENODpLjuf&_bFPnku2Bub_n{mF%y2XL>KH$qMbd;g(Mo z)$-2uU9)HwMJYa;oaLKs(@Y*-p4w3ym3E26G|)*8<%M)(>%~^o2yFuuQ!R}3TJUc3Q#I*}{Fa7qU%=>@hZCL8&E+;L(y}W2)ix#NSeegu z^U%+C92swCtoJIVFlI_er6_LhsdF0Z7!<2l3oFpi=-?ZcIMNy=#Z)lTxYw2?Zw};^ z7L&pc{?!(hB6_LW+H-q{+?yal?p@~b)ELlH3ZA*$&A>XA-*}?zK-O+`0{6%JWLJ?r1wO zD(4?FqcLfkt>PT!ti|VbofkA42EBSGQgpXG`dGWl)F7&QT50x4=k>ZGMa}2n<>MXD z#^<{OHkwT798z~?_)m%Kk0dn^mdOd_ix|r5cq(Q_-8l8R~)cEk}++3I{SKVl+(QCs0=W0 zA-0dvSx3pC)sxBgH`k7Ih~k$4bbO#&k#r*cSXy`6sQR7UX#oom2)jan&hSaRV&T*} z>q*L!S!*y;F1xWsij_m?)eR+)orkZ=-MZdw@vE`@v`1#U1eU+(9eea#pitPgvio=g zAA%A5tT+velso(GC7m|P5(g~aT4L{+vF(mBYmU+6hMY%d?5l_9c8dd2$GT;h*SS6m z-Kx-HWVZftc;i+9y5lOPt8I6@vYEq(%QdCN>6oIXVT%#?VB3wQUaHC9r&?I$Fr3$W z@sBvEo}8q4kHB$MAZ;sg4yRo;HCv};DGc^sdg&PJs%@FEa{VL!-}xmDzcn)aFi-U8 z{4KeZK&LIH!8G?Rwi6ds6Gcik61(MX#6XYO(oJP?xX=@giRsG12VGd>d*>HBGt0bb zvv;zyhHn%2u!3sVx!g=jspvstUoMPnseWp05S4a}?Yg#cO)k?y36ZpLk>YJj?W8je z8&}j^;8pv0xbtUOgn5jPNJ+oVWp#a%TN4a~s>1bK`9nWUV+9 zJzo5%+I_0(4f%`+W_4)~gL(ALy1>#%t;T2fVaUaiJFN2i_yh(x&F` z``P;Ul%h+HVs4AkP?q!r5TW0iFylL_~A(@H)Lu|D7akO!HC5ay#xaq(f z!@O6OzwKT65O&_mKqCMA2w4zp-JZkryp0~MA3LcA;_9FX%i8;Y230Y~B<)<#I3hVU z2+hl|7Bo`!#yj59yicG<+-p(5?qQhve^ zunE_$S3;4M=iTd0qjc>o*4UY~%bILIIhr*$D?`zovY=v1X)*g~7B=XN$ju)@?kv)@ z*;$mE`dJj#>TRj+$)`z8f;AqlJJQFUvSPd9v(H&hk7#}pBeE2r@jNqLiCXZo^5Pxo z9;vpC6;$54(@EGBM(av$!icgD3y(Tba=5>GFn(pdFDTZYH>9+*|)= z^&^6sy<5%i2m|DzveiF@`g0m-aS?CS+Cwem>v@!kCBxgNRFK#)H7m6gj=B6vV(oc6 zH9|AaM~7QQ?s#$8*-G>019U6a-XUu=_3hNUZdM*(7Ts@{I+uIK%CN;=XF`-)mgM@i z#I0-$(cda;?ps3HA+tydYwTXVZrV@yDa3=4)y%r;HyRIiw3kk^-caKfoTRn5VSYrF z=dmQa=F7uYF;3^NTBT$B;8pal%T+mtOM)7Ehub=yk~76cVSLIs`$FfNA=(G6@DI}D zvu-Z{HF)L0p5pRq7bQAzx}_GAInO2D=Sa{xZkzW)D=b6L_z;@BZq2SLjjm=6U*%e+ zy^GSpyB^0nEe=o??}(iw33Z&fuenTeWND{Iz#cm{qimO78(c7oPu5=y@5Vl4#K#wDwNcm0jTUlpvw~FF#>h$l5^Il+Ew4J4j?yi*B$EL|E5q(?yv_&y8a{^2Jk4>ys}t z-uef62(mXKVw9e`D{7UhNoSK%j@)AB+In;*wWMTu$2W9+MWWdeWW1z4I!H zzV5LyyL-);Xta5Uic>-cwWw40wmNv;`G{fNUTwQ{&4UuXW8R%ss9l~Va(zYCZuKZh zddvI)Y7Q#5AL_*V&T6-hvXzeryJ5AoJi&^&-KUWIq-I2U;Sts_!MYMThoyU8QKz_= zXU*z-z;owS|DCXWOgD_FQ6C@DDNS7J6eBt{&yi60^NLAiH>WrS!q- z7Wab=t=`dA*Xl}+2_|G5nKnlWNs<<&r4EXHJ4Y@+`` z@0s`aA62Hh>N-&CpOQ_w-mT7v2s+v&M89o0^&-niU<1j{v%N#CeAMDt<2RBZ!3zyj z#@Q5~d_f8)=%P@+{D{2o{%(?$AKl$!2DS0noikLD#j;O63WI`(Mc%asV||*tTU>ZE z+0L1Mt`h#Fj8T_^lHN)-1(5D?vBs)QE7C0I=Uw&GNA_b;sJXo}2utN+Jx{G~r7l^v zBQ~)mragc}z+}X0S>GYJyKE7?nVEjHy`}c#E@7P?Cci->Xl@PjZZM3D&qyyY7n^(6 zq|n~nJ9^0Ym@zZH-rcIaBu=1>xmQ8ELuMR~c_HC%OKwgfQKNQXbki%*?#5c?G4gL) z){{eH4evJCSfQhSK%sckkwkH(^U)o#|*!+h^G z$)*9jwzbjzxWN?>-#K-~+&Iy3v`wPmU{NXx!)DKV@h-w!t0q7am3a6~GK(cZN1B-$ zziakRKgMWq^xuy{iH9Q=V0Vh8;r&Sc_+QgZnwFyZt z4JxfnI!ld`YsI3}+HIt=NMHJt@*Z?cd2>CJo81)@NG90aA-T^C2vew#PjRt1NZ|XV zrpISwRO%;Kwk5tbWkyNF{3iWH_FY_e5s|6RxNPj)R#Dx!*jo;T@}4Ih#skZJdmoV~ z8?qvQbWzrl_jHc@k#;MD@Zd?idxDdK&PlloR7=H`TErd!SG2lnuEXXy!X&GRGS60V z=Q@whx6=*8N(yb-v0Uv-g!XVpF%}a;qjh1QMAuk!3F`fuQ(w%nMWNmlN(%w}yXtx- z3%rt_iML^H#RoX6K5MI<^Rg~^)Pl3}6?N@4wCy(K3gg#RJX>&wi*25??{ZLWG_{ue zTk!?9`ojYRi#D3~q8k1^Nk^>b8?z!O8gxx!s&l6h6i_IkoOJ8JM$@3ZIa`HDv|247UYc zpGTiQwQJgfs9oDyXx{$C{s)cki95IR5}ea_MiwX(*gO`X_1@M*cN1pyWOUTmSh?_O zzzB%vyx#A3j$<^sk3G?B9&e6RF8IKWVd)S3MGMDw}iA_?W_+ z{G;cL-1l6vd~sc93(@){Q-^%bP2oL)s!*4v9caN;chHwGsYRVqxMZ$y&Wdr&rP`aL zSEv-W9lfA+Hr0G1$0e-hYV%)bvHf6MmD9eVfT%SLB4t4o(`P)H|G+rPTC53K}4%u+)lcUyp zpLvn7<|=&6?fIJ-CdsQ>Xrf91t#uv&YCQIz3cY#3M?x$Um{lx1R67!?Nxa|dUd;ke zGkxZS($)v9)pOP>G~DP}p|$*Ma!XkAs*$i5Yb@LzExSNE(urM^oj+$Yp+*6jPLhj_ zs0JyIX@Ar^8&8)Cp=-poj?F#-P4BiEX4S;?3ONf@3A2-KWh9NaQ2}N)%xDSbY|UnI z0*mGvX&0)-}_`A?SnmUW}IQj_$1!-y05!<|MJWLhaTBlYt@z#E;U{p*=37& zCHIFT@BueO(~<02N_F!HG$|N8frj#~{IXd1(B(B9>*c&erJ5NleVVW0#trwpe#=U1 zWup6n5+qca&P?!gn#&2!4gU-Lwbn59lu7(=+pq9zA=TW z93|T;EKj%UZ-93KpD;iz9;eiUi+VcZiNRgRy8$Kqlz;m>L4G5>M^ueGl(ghlN%*~y zM8tNuuNKn-RyA$Et97IqY@8WUuV`G5Cr*wWmkQe0*J;Y0>H+GInh-3kq(Qh`Qwn?z zn3G4*0VP^LbSknE^oPji_rqtql{f*%X4tkXoNs`}q0fI!>fESIOVq`WI+u{vl*gC% za4roOvanEMUQD{d-tIfsuqT3M#$aiA^LHUgfKZg=(7QoIrJzFo$vVl>(FLo16NBH@qm@$^C{5yP0wA|+m3#4w_Q1~7F(0hhxZ%%})1 zV=@5yE%`m^q?(4U2$(#YetF4;EBje^^mx_trEy0ogK_EO2u!>�k&`M7!Y zh#(wO-MSBZ0xiE16H`b!<%W6$%it%Vbt{1VCbxNP_k z1`>v}0s|=(pZ)33hgBywB!w})965~#Nl}R{cT)@Q(zFi zzaMbQM;6V^kBqxI=f8Th1v-umi@OXmM_2rj)%s54O7-zgfaZXD3y4U8v$}f$2mJQO zuYc@4%2@y*-CO$&u>ubL`kJSqzXI%r*v-G*pZ=}wPl3NI>{HZlGuD;(_5K_6Ujb=D z>-}HPWc|iQKQE3J4_S{}0FO}r{RrUw4zphX40yc-T=@47|NYf}CGlUI_^&JcHz)uS z_-}apf14HVWpfsNY}VKZ4!a@`(A= z4E*P_$jAnGH$V7+ zB?hCTx4FMG0<9W_e2T1h!q}_SOCQ5tw~vsz*f3f$q~tHZ)+;!VH*&7SI2cSdzZK6S z_ZRV=&(I5bGYc6RICd5z5)VqQA-Q(oU++4-dF9CvuQXsDm$6J4N^Gbm4?b{t;r*%T zfJ>3pVA^znFyTJM%b<8yUflS(ceUfoOp7Puh7w_&%Tsm*u0$jb0<9%^A`O1#1Z0y_ z(Bt~ikK&*p;Y>0(T0+KXG?H~wd$h#qff<<_HsTD&oAZaAAuwV1r5)e)31oi$K&E5& z6i1YZ4&r)OjzHqQUtKF`u;$J0OmFO*gEy-~8@EcuT}yex&+$%;=wEe>V_<<9USE~Y z=xwI8i5``X5W3xh<&F0hM;1-TK(`I{c@*U>E&hpD%uC~^3JHm62u8Z-#WZ4QJk4OJ z%bp~^1~*?^Qw0B|aYm?I92=KDw&Ji1L)^YS}@k1}xcoL%nvNOLv z`f%F@2>{RP!g27R?+*yPh@Wav6zC5{yXUN9{K;S!M?BLP+B8UaV;((ubfzDluYzWO zjodEwQLPyyypQSH(NPoPopQw>1D4`WbqcmB(;t>fkzc&<#Q-Y_X7M{m&y0s9%J0(} zUm$2LHs+z1euSOsPGvnE+j89rO|zUo4oQjT#)rVtD+E0QG6)K8plYT=4Pq-&^on?@ z+1RS)lIBxiN8qTv^qdc&9$w|-uk9je8U!-~p*`3_nJOgRgv^=TwuKGT-})w)MKyYq zvnQsGiD}{LX>&S;3QK>CS=w9hKP_s-7+}ViVLnwwR{mWQR>AUn#yvjs+*enuDtl}A zUW}$ZYFVs3B=|LUoD3qTIne7tKd{CCD769b=OF_yED-mIsbv(65%nX8d2sPJ?2t*_ zsD8iI+l^L715>mx!kChK8GCb1@P9bGp)X{V3`F&7$)r~C0#xm!(=*bv;2oW`2zr+@CJcz@!+ zHGM<9{G5#RTl-1sb1??lLd(_&CuBu6xAe+{D*s!gkEpwFA-meI)l=F*@z-OQ$WElC z4l3%`*s!|S%YM;$EhR=9E+?KH|>}ai|0D?S!_qf!NW~Q zI=h4Pign%Zr?6p_o!PWf(ML3kAriK8;T3fwvd|Yg)yOCDvsGL<)at>|=?Zqe+PP-8 z>R?=%qj~iH84~`CHFi7eQ$=Uj3MVc=m1Af%f<3G3j0un6bk5gdE!f8B>=Y90Mv>Zt z5$FY^G0h_6z5tLOTIVdHMXrk#fZS1gImtgHEzK7;4Ayu(LIo!Y#fI-U%hW z0~fgr3lg1pQtF0Qrt2n?!-2itn49HOVSK5(Bz#B7;QaIuvUcb@?E={RO!}!{*46n0 zJfjJIJM)G6<(B@4v*I(u?3Rph(cRFy%O%Z6pT4)_>~85{Pmc!%A6(g3^;!0S5Y;$5 z`nV*%n8t`KWU}Sle77~a&_DSgND+cp7meFc;7wAC@k(PGh(G>hoki zW@FR49ng)Pg?Z^v1*+S9^dLU`RbDAJ$`3JYW&~aws(^@+r04>V4}oCv<{ywVD@LQ+ z*YrlOD)^GyKaNigG4?HbMzGj>V?{&iswtOsrsjnxMOwYsd=iQD+C}i}Y4wY-Ez(hV zcl->F>$9aYSP(I<)?X{J10L!BCWF%=;0n7$(uY-3Un}hkYUGb>8ItVcv!%4>cB$SMr@7fgfRH!-&&kO?HYmBzcVkYUO zPKR;tzQ}_Fih$iC^e@3qz`qdt8L=iFx7DeK!J^$R6^Hq4EV|HXb=u;Ffung_W48yE zw-LWOa42ra5?`%JZFye{82N3MHDNw95MFz2iLSFun7WpOKz2z#og<5n4&5 zZXL-%L7Z-eitl?}EU$)HE&L;9_NRYs&XSU(>RM!CvDyStn;%qV^+7W=xbEuL?{-gB zPiF%w1*HZ)=j-(SPuUHFfl*=WC8uS_hP7dHl2ynNfBKT}YjO^TvC)v1atAq-&>`;t zLUe(Y$Ay3N-tGpvaLVIq2ipg{$|BbSk#=3tFqgsJNU4jLeAMK0o360pZN8qi;me8Y z%sDbxE-2A{^w(cuX1QjO2ESmW*hMa7LT+wE(kS+U@<(Hv=zj6ajfS_>ba+1Y({RHvIQS`B~KwFyxp_9OX7`KK3LkZ_uip{adR3N0WC zyU2x=pV$@4vzzi+g>K$^8R~-e0hIa!~Z35;Md3(2dAPTP4m zLkz>i64$<>`l*n&=Tf&SEf%b(XAV9pUBeF?iZ({gc@#7T&Jgj#8IkX+PPxliT4lXt zez%+fT*SZ6`ooHAKqU=V1k6}O4^79PVwXPGR{s*IUs$7k^V5yr0zEz5gW3PvgbLVK znzgk?-Z!Et2}Oo-c)|7@Uln1%#Rf4haa0CmqH)MLQ-{)Bi{3j{xNMU=+1gUA?UM!7MvG{8}Tq|&3j+?KTkXxwMMVE8=LakVa+CA7; zg_8G`1Y-o}9e**TTaZ@zZeZ~WssI*=+ZZ2$7mV~sPlyYrA9fVYE2E@D&Kb)b(@f_I zq|I8Ryk^AEHi68ooj^p+*={6laYJMOWfRd68`-JM23Zlem08^vcqz`R19Hij{V?jg zCh};XofYBN@w7&<hE1A7cBi#uitT3#L}DYP()1`$0#=*S=58TQY_`DlaP& z2Gtkd8(YRnbnNARcl#_~UalyTohmPhhsR6Zyk#Yjfj$e3a*O|#=E4R>N*nHtpX{$yLyTb(1S$6n-B0J~E) zSK0l4k|bmNtW)2`81>Xx&b{+$t)af?wcYwN3mevfk#Vc)-1bqD3;MM0KS{ycL7KaS zW4oLhxM`OjiX);7T{@kj><*7s8=NlTI9xZeSM!(tI!vO{ob^wrgZcU2XTZzD5hrx} zH$Pq~#Kt<*%j`z`?ANOCD2!LRq~x$`c)z82-5mWrL{?EOMDXkmFqU=8-*RMX&E@gq zOND4w2nCuxKxI%+N12jC<9R@1*6b+~U9F$!H9&j-E=5K3_h(tO55o7zg}j1}+^jNo z*g_BY(J9OCXk(&e5?1c7T~h%p6l^mp8o9}V@kv-L_Hem_wqshk-<;y#jbd7D&d2qN znM!F8zYR4-Q9f3o#>Li!Mh>`LHQa=f{Qv|b;TMxLLrc6;?tunl$XA*#lp^jMBQ5Q~ zcJw*5Mtg(hVM|t*sS6B$WVJip$gJ%jHQYCj7FMnYc>&Q&Zq<3cQX*fBqJXC$ke zQDN}_EDYf_65mH4$bqI`85M6;@>O2k4f94!z{|od~DrPDXLpGb0ewfei_KP1kn} zo6xb^W;{G*E`ZJD>Jl^ zkM*)ANA;m{YuFC~k2xN%rPXOp@0O91HB=jApm4LFSc$kEXR(VNe zR?Ek1?V=ePV@+aL6kmHqi&}j8j?6|SbNH_~vnFxi_o}mo&ck{}iK$J|tmud$$|J~B zkfUe&CKip{cA;L+Zww+k1n8k+$}vc$Il3~^=90e=jR%rP*)c;fpq{S;^%r{gp}xOW8#?0I5GI^@0$%=5 zSU0m)Gv?LW9}f6r={~v2T6r4LrBd>OTcQu~{N>bw!RVFFy$m5la!a<`&b2S(Vyzu!nRg;+ej@l;wD*Ad+9-lb1|H};a~*bRRF^7*bbCHs;jUq_{u zfqlX)v=gf;OAa!2UX|>Q1AY)-Wy)t^9*aDvPZ!2u0z-|>!A0KRvMHsFVwJ0A4B@gW z{#ppx<})*g`tS&D5w79H9F#!}3S_|9v`khToHSSbB|dL#OGF#KMv;d4#vEJ0T0MKw zatQzGjS*YO&SFL`Z4Q+Xg#RCA?vgrZ>LxeEc<_1w=G1v z!@w`%^7DOd8pGZ|Ay)yz@gnzv*X~*wJxV4=MDQlP%i|XM`#%^X;?yT4T?~C|B(HZk zDLebeGx(tW9mITMZwewBA8-SjFI$hQM!>dkmm(|T!B;A*p?ez!Hgq;16Okgv4{TdilG zvGQt@s1b3{ywYfhuoPc(!Nn4<$=l&Yfq|A=GJs4i=?aO@I(=4K@=I$roViH{kNS8i z=cA{4-dwHK7X&>@rIe$(sr8g=kt9+xLH!|%WSj(N&E*-b<=4+&3a+anv^iBFpR}{&7yKGaxcf<@6jozK2s2r{ zxu!>8->ds}===XrHmatxy*HX(=htf`I36w9vNGdQIp!w-6UpDFoAJZUyal^ngz$z) z8U5x&>Z?vl$0gka(WLe4Y^JR~;kr_>70TA8PD#%=$8uBi6y;L;zAB|CJ#S0_SuGhn zY0VHjb@Q!H!Sw)9i@cRZ$CMEL9z+Ig=N)l42(SK=rPvZL~vN)_TBTOP&@- zQAT}>2kB{D)A@C8K8_9wu1}Irl*~u!<}cNc$hq)6iyDKVr!%|j(G;i*d*5Gc)Pd={ zjkr-?xinr}f@KjSxnZ+%Mo(L7BQwUyix5% z+{+bcO56ss#Eg&CTpP1uv|{k~lP1~M354zTO1zkMvV4W;CH znk2ngrm1Hj}s3Up`0q3>1x{_(i3%6Y*!rnSQ(8mXAl1>Jb|UI(5>|CXZ4I z+Dp#PPrYJirtdq6%?D#zVQ2qQ5Ws8FR@VLrU?YS|y-!-Jp-$MaCrTtC>SR&WQmWV9 zNyz4z$!N5Xrhl@5AdJgyriKa90#I4{s_oW3d5jIVMQb>EJEF+ok;7OuXUTclzn0?g zcF=jr2oG!<5SaEp)7SbIDEIC=7JYjO+qpfFadca!jH3A!4Sx<&YEXB}=lTlI8} zFh=y}%B*($-b6k~I`lpG(aFpl-s24W?c70VV~e}bC1s1X&0X1|Gx)Os5w2CRF}J(# zTsp>~4?HcF>7QzLBHO(QQ;rpnuf`ANNp{tuDVX||a6C>ksd&UK5eQMAk?$ktJAQ2E ztAa-^Oi`nceG%>h7d|?DnDGKA5DuO7lV8T(;@0EZ@!PSX%uTYW)w>0VAittWbY?ua zkRQ7{?-g`jra{=4?ekhH{?Uu|+=1lr|ASH=kab=27N5OjRxY)FyP0tq&!g{ruyBTv zkt=VFN9oD}TifKCW%|yk*0PGQZAqYxV+xR{@rWk*p=Y31 zA2erpXzq`n?Bf4h5dlbi)lt>k@B5607TM3;EUEkWWLpD#AHiCV_B6%NFh=GNVfc;y z6?|Oi_#L?g7FyNug7>ql3Tu?b=&nu8dFex~#qRg(fK*|ln0l=3;g4kd^2ansOVsPZ z_Zoo?>VYpEax*ut3N53QlQHk8(K`jKWh=C)=Bk7S>j~H>=UnC$+k=Xlms7CwaS zsTGgODD3lYIWBjH`Fb>M$>sNsB-o4_+YGT$wd|59|7U~Pvw7Q6#J1Bt19^Ss2k$p| z!BBU9;s=4`0IZ+WiTi0?YW$RIGiB=r=;VA|7r%LZIzW?nXPs^FNQmX3)*??VU(XQ_}%}by6tWFO6a0F zs_BEX7yaq58!rzmUmwVqYU;d_l^KLJ_cEQgsEP>c{Yrj8&~uQq(_eC<*ZmFtwvR@9 z;BlXcH~AdmGLyJvdJw-@nB)I>HJK=%<^$}2&t7&YJ8nauCfV6?d?wX%Ow$^+au0QY z2|p*7#y(gGAQn{;7fdCfX36Z%crii?CM~origGgHy;5)W8o_eQ9F+Zx+o%T}Z@OAp%Tp=J3)sbjUl05iNJ&m#Q; zF$rv5I&!9Z0KQg@+%9!=@R#xX-QLJt$_pHPhfivM6T4Q1HQsx6>EV<>tAF&Ka{GDN zb+QGC7w-KBr%Ik~>3U>bT;Oo&!u&l!$4d4!m0DGA%a=7+@mrw<){83rFY>O9)~&!? zbZ(2&q%eX;uoGl8S~-atgTWsZ}# zb=wu^$*U{Q5rb7CQ(5immjkwhm(r55;fu@txlwUN@OMdH1Sdp!ItO}X|n6zI!I@qgnBi}D+Wj@Ib%);IYdpjFr z0K`5FZ@?hB_t8QcoG4rZ_;g49(>+zi;cr%7I;>vt6SMC>HyppR`5rz>dF}*?#L>Rt zcH|#khdG2kzwUP38(SLUE=?MZa^4%4G{u<}{VacDd=AB)aou9?6#9BmE0)J@_Hq$T zJHMNAc{~nz0-+Zevp?{(msGS3Juj(66*}ifW`LEt^%WJ-_%V_D6LEt&Cun-xYwlUnagn;ixR$NvquRSX{`}Q| z`zn55*Fy9>M|Ojk)m-ILn~p zxA@UWof7#E1PgjW$#o)N_P1gxvD{ls6356bIEoj!H)clhGpn>M4(AkYV<2QDkD zoB!8eA6CTY36=zfq$4}P(p5U*2QLl`>7*+!o*GRZG0X~l2FM)HuH}Qp;=z5!bRW^3 zP`nu&*yo*3kW3>YqxF%ng0=pUZyrj=nuME_@%7F0pX3F0*=IULzWnS^@I{r&8@2)K zApgQtx3Q!9KNqVX0}qq_P(aosru;}b6gtcrxNzgGy`2mvt;?+7OZ}hm?)~*w#%2eu zpZX?^x6A1ee#$}(;I6RY3b{;^d73Fy=3w3i+mVV-HXLfJ_RU*xpj_%4u}pn`vnKN8 z3hey}uy_eQmgmw+XXPm?fMmiK%ekN`a@M&XL9di>YyI?^5U4l6<4~P%kO~66a>cpW z6&Dy^Z8$xO*VD9G0jgf)-v}%8YFgj-$ScfE`3_)?$fYPDnUq-w-jXuKG&@X=CJ818 zp)NAN_@TOLX;|WNcWz;!(!p)nx61+41H+3-x(#?9r~|N&4az8;I*XV5+js-EZ*t?h z@J%@|EB_dq0ID8?1Ul0)EvknjwS-97$Aqbz-(xmga(+TH?A zYW++6CVq2@l9k(eGR2H3u`h>N-JU=6wDjI8>ln@%e_iTMOmwVjL83PSHL*K)9^Ev4 zi|ucK!-?y;O_XBFfnWpKqvLU(zD#j!-oyfsXPWK9WZP6dY?Cq&YeK&(xWLpo$<+M6 zLib|^@cAyr=qt58Ug!@l$Z;ciecPO+TcR=p;g)hDxNEJYM!qYY<;w#p(akF|rAiRk zA@*{CD?`$&MSX^g1z-k{5y=q@J6e>X z^W*l_8aBZ@FvYtS`D$!Sh!gk^L}QTkl0jr{gm4bOP{V&f@}Y84ai7l}D5zSegy!U$ z^VV~&x5Q~OsG~c3>D2dtfUlx@d*jgQ2C#I{3?g=@CykdYE-sXOp_5rX(OrWMMj@|q za`!OK@8>#{Pdg2%7d)`-EChQGvO5|(Y>b%0^f{3pBd)>{Qv}pi913S&NDJ0f)=lqWjr-JPhjLX6unhe+dU0 zZWkYpj^ONnNGOCxPOZA@j4@+(S|0Em6`3ahq~t(q30GjzSjgxTT1NbB`Z3dpX$(K1 z;Rv*PDlp46Gc;6gErWipO&w&=i!*&)*A2P7#-<*HmvhRT9`~9W()r+Y*OH;UA*1#U`2MdV*n)XZS5_C4Co=F7t zZo7YS(y%<>CLWMCh|B-dS{%dk5Eq(VlXcj&hSsmO)No$Ubh}6PP?P#TJDz=fzaosl z2HmFOB=U}u?C}b@r&>y3!&21cmc*Hn0iW0C@I7)bPF8wex!s!(c|IHxT^zUL%Cg$a zt1cVJzA-T7SQkcrMk?N+&X{SAG9mBS=6}!!xq2GXbz<%QAf52%??#;W!|I3N&DwJp zmO?AmCSVE!^(wIx^41CMDX2_nH5rr%htlf%WjFvA-5~7xSyQHl;)@Z>8v3hsqNq-s zD$NHD!wAP?BUo^A0c$GmE9j7gL2y>@_X;OYvEHo9yRew z@l>c+X2+k6TXY)QRg!Q>o@PL$#ZSQMd8#qM{tGx=*etXR@@y)Bi$X2u!$TI8I&~tP zvyhs%mY?|RDrVHxQz+OdBiXlO>?8O}x|YoF_KLyd0bl-8&=#D@dc|=C!Tb-|0!FGq zs$n305`M1Qlac39Fi2K=T>sxiWfwluqb3k3;vWcE#VV6mVIk6WCBC#eljyOVZ(+fq z-&>Zh?%!p1SX$|5&RH2dIovb?W)0?HQMDP5UeOq4g2z;1zb-JyW zwhw3BGw>nloU-@l?Q62$@@DeZ0)xiz9WJm@fEyLv7PSmXWFhA_>x}jCX|uyJD>M`T zsvaB_7pA6gEO)f~;z)Y$-EnjvecCV|kUwlv*5n1VMKb*HhLQg*f6C&Jf*ouo=x;b= ze;aWD=S#<)C1Mg~(97qt4UU1WRq9*zoXJ0xHZyN=DgQva#<2jYtJ;!m?u>u(t;UM8 z&{yzp3U1n#XT)}$lD4^_)%zhsV4GV|?LI#+bN0PJ27@nLmUPSAhuL)YJQ#jEgQI4*!@SSukt93ej>Hv0<8AH@2?q0f5l(g*e=(i!f_DCJTzq&HW zr9lo4oFOhFE*YJfVH&Ux9?{@l=;fDw*Yxku805ap>nro%?cMPWN1j6heF-{n0L<6xTsBVWu4OUQ=n4v$%-1SHaCB&ME9e|@H>cQQAT`y)oOE^Z9(<-mxp zgf)4zI1tWOKM1p6CvSRVM+Myc+nrSN1{IAW+A6Agy~oy|QM5$yGTVwVoci zAW1LsL)T3M`bo&E^&9VlsRbS#%FlsFqw^&;Ufx|bW#WC?`o|qxhVgfbN%HA^HzLc+ z4am3A+;IMZ? zzI_rGb3=e}0kVxZaIfY*xJvw(DJ|}5=5aebo}FzMylfre&aQlJ4^0b&UVaViI|AA5 zLIpf&WMR@$+P7CMVFeZyc^RyuDAM;L$BY3HhN3rgThmm2RwE&@0QT{}s6qN3SI{X25jQH|alG&b>WT+i873*rqgO*_B5`Wt09{}@bmQnm z+yqFJn!x8?Q%*Ua$+N!@(YX~}xpV>C==MpqM-+RvmnM0vbz748-rsii?xsQXb!eui zt$H4ike#U&CvUPZg@u0xxK35vhd16yoMw2cc)EkNDcL zBooG#pb!6ay3>Lr!;6ZZR#n|&Ht3XKUMCf})OWfuu%a5OSI}*Ow#3LvE8FJl^sNcb z=(N!}vw!W}(@fL?n{ClM^{W-^rdhu*{b|MWN0|#hCg%0v-=a&|TY3*$+(37VUJs@u z;y_wo6Q$QP_|{#gjredJ6tblMJ~F{~h6FP$4`FdnlDA$(6afuJbs(-oL@neRnEU`N zy}f=>C1k-$0e_?*;5_ec0KQKWDT#V;DSnMaZ1_-#Mz$G*`y?#7Pj75=-EihVXvVuc ztSNua%FqM`_|<+6?bX4X`kBYpj(LTqOvq^~>*xPb|J-n`wd-#igBkq=n^tg8s=s6B z>dpee88i8`{;N-x37Z5rDP4ViWW$RvANTF+fxRGODra|KBN-SEd0HL;EaHCIiU~M%VZ(qz9K$|j?^7h2%U|wSJBwcf7zKQ-KY_6LVdyuDI;gpOFdbe z=?~j45c79Y=iOXaLODP{n`G1dEwHBSqmeG0t*1)PS2&zxZfH^HjgQTP8m9}fKr`>s zJo*8cr=WM>=r-%EuoB^;*p)kIkJ z{4L*Ou=P)1$M;_jVemyOo~$2es;CVWm@%H;sk-9V*XtQCza_*#g^N$#Zhv{5g>-fC;tIm8(8Bl zltRIDt>2uBe0lVRQ&-Wt;~&FuAIs12WKSbE@(-S-$#B0@s1A~Oz_*qw^g!a&bzM@6 zrvI!&-R4{Ei+PFKZc{x(hs6vm_D0d!^J$+QpmzMUqFqH@u5PGR7l=|`AhOo-c5)#e zy;mZX^aXFSLSI?y-0&D!eEeUkgX%&rb+;x(oK|K=ZCNuq`6tF7VHXYF?GF9Ant$H8 zNn1`I2nFEQ_}Y-QQ+DTg#s{?5%su?e2Ctc-cSP7Fe~-tQ@6d`mFsr0lI1q>QlJ$Q5 zU|O?z9iVs)bPKH#65rPXZrW7I*GK_1jLu(1;h)Z_KM!BjcC)?EG5C6rwN%6irR;1= z^DJKtWMU||$AX36(q*ZY1;RC*g1h4Lu#6jijco7XmZ9ZcRC3g6Y#%KMe}IgfifY>- zzU`kWH|$9syahEB5$iA*4OW>j9J>x|maHDDy%hfme2l(Yj+yF2Hz8J<^j%1EoY6QF zjx$>MR>KT#_47wPb=gavy>FV{oeZ~X(P3iu^YnV0`d)FTY+5oZ#0=9DA??Vn}`L7LvI}`xt3Xy75slZP)~P zV#-PmX1=Z!XCy)ZG@&%hl+VY3$%-tG%Wy{>a)q8bwOTru@bSQEXn<43^LuqnPjYt<*X zLL&6?ji67e0pve)MP)_GmGev|{Q2Ah(0YMb=`(|5DH|T>5?ao_NhdLdQy7eY-=A_1 zeMUgn6>!o1oio63B^n%66N;Ymi&S?yZ#c7LN~PAfrw2smUf-j#u3rNYP^D?$gyNQ>5BE!kzRs$73_(75WKUSM^PrDJs9k#3*aa?(HMSk7W*sam) z5L?N8S%vRXhL>EPr!7zSS{EA2HG9KGYq1{pACh-;`(sAi<(b6jh5CUaeX^_W4(y$- z^ly*uH*k%{Wwgnxl5~56DLBiu#)eTc_{tohYPIJcDuM6?d4h&e=A~}0imB88^j#V^ zU(q#JHGCbzhk8|f z>?8r>EE?&c^Hm!BL(zuLvRtFN=aKEh>Xy8k<`t#uhVx@Y2Zyw-6;yDY3>smvQWV$G z>i?iI>IY7QB#kjq=9Eg$4b8t+3jX1BB3t%OgQ)F8OLB)WF0wllJ8BAyw^yy;lqD5D ze|5L}*6wg!FrbhgrCv1qe$PdGl~nhh;&cbJs%-&Tew5PgQ$31vAZ|#?(o%I+*uk@Gy?e&SqxcZ5)0=OZ`Qc%#qM3)I$wud>|Hj>w2e9OPm)&2hVE`D zUGPMB_qF@07Qc762CzU2n1Jv5kWnJkMgMZ0Xvh$@FmMuzO%gCv;$E=F`NK8BJ9$Xn zlG3B!vw<|(Tl`%Jj(uF`UY_aN#gTQ}Of)`|%K8PgTlo<>g5x9i)gmJ5yscwR_ ztA_JUTyt@1#0n?YA|L%WGOrM8L^5$Qg?(obT1Pmf%#k@#yWWA&9ZKXYD*EB^L(dv&iuZgnbiR>X8ACi3 z0oLCsU>Ccd_B^o4acJFHo8h@f_l`*M`#q|o7aJzTg?wD(p06~^2s`O_kFWxxtwl^a zg|rzSdhSHZ!9n~QFOTAtBegH~#Q*pz=YgR3c-$R!ioj(R zUQ~D1L|60hfXxC^JwPmOFRxz#v5Yz@YbzXudLg z4{UTnPBB75auY{vtGb^Np^d}Z>SXxb)m}TPrCL}Yr*E+mXF2f4KUu=y)9S`R&;vt+{(hw+mp%CmewnqAEY4;P=^pf3s`s!8r9zeO@=Qz}bYl z-t3!2#WX#R4?hXH(g{6ggLm(&=|==q0B<7Eu`5=#!w4eswLKzqaWEY-r@r`?z8Ig^ z$KT(TCKkJHa~I6#=X^dbU+2I@chQ^w9;x9DMa@}lK{)Hp2%**|CFaO{5=5g4ah;s; z{+-qSF1D-=fzf$qEKR&Y@bwRq85#dHUw&*wWaQ3-f74U$TqjF#hJ9CMzFzME4f2+X z>`%uyFBgrFa^kv(XTsWhCJy0d7;1kF^Tt4LqFnyb!5uSvlRS;gsZI6pa@INq3_~mw z))8}>oqU$bWoj`*%hOn}?JUJ3Tm0qR)g@V1WSBfS72gb<)_b(>dySi4Ft0JJgSOYm zJ#(&6-_DDV&4SY@&E&fZLEez(s=0F3PR-PCju8CMUItRI6Rp;XYpudo*%!H%L|W6g zR~!-Mg?`M&xnIpGtULA16_Ta04|(+59D>rdHmSyaj-($8^A*OX;cCP;8~}1(8PM|X z58@6dK933Z$^p!pK&01~8a75Pc zCCy}4yHJ$q7^)AeUPa#;HtPJ&F|ilo4XG$vY}fJMtlyglx9&}KE}|0^c7j!470k;t z$r+3n$RiwCJ3^4^W=<#(%ewc$z;w&m$pVD`nq(V;gmX2u9PF!ic@=lfheC{tO$63& zJ6lc4XCyomM>|!rU3!-f6|KNH?U_U=#EimNFf3vwN%VK;UyzdTM>&bQg%~c&&qx{r zL0tHyZvv#!1_kpS8{gV?irWSB${jHg3xfH@2r^0!Ygv)9B#-v-X0JwT?AQK z#H#&aRg6|301Iq$hAxAYubi%zfGUBr_8ZC#MPs&dQ)AC8nM7z>7ZUMxNe{*V8HWhV zti#FvXc(#!84RZT@%oGI=WX2k{9pvBK7hkG(B(H!PxMX2`0>JFL~~9nDz5JH594ZL zURQ~q{X@>YKnhGRGwSR*eT=ZAUz=vB46qO3$&GGbj5vNy;#;hV=~axH`K~YmwX;#1 z(^;dGJUdg3gqs06h<{O==B>0N4*v;`EgHKj@uPOcxLOh__-MW|GNMY3$~E_?j7a=^ z(O=K#OQbg6PNvz@WN15u%8%~%R(M#lG8xl1MmL`9Vg~+*T^o0)Y2NzNnLwNu2;i%= zy;E_!6rgJ#?|=P$v;^3q|L@tp|8LLs0V4nJ$;991Z~iNZ|2p6Q|6D=r*X5^QuLL?+ uXub-Zj{5a7<;IB);MRXWdtb=Hi_pRCUXznB=H#zmUNW`1P<;N@-~Sg4KhHb> literal 0 HcmV?d00001 diff --git a/docs/images/performance-test-workflows-per-second.png b/docs/images/performance-test-workflows-per-second.png new file mode 100644 index 0000000000000000000000000000000000000000..8c4b61754bd45321b3768bf362ebffa4aa5f9e17 GIT binary patch literal 80363 zcmeFa2~<;8*D#E&)>=ihT2WL|Y%R7{(3U}Dh>D8V3TjnEkT@eUMCKtR*QY8_sf3m) zRfJTrqB5iyAPgbVq5@)w7y%(95yA{f3?T^_Ztj1A)>bVf>s`8BL2fGJ3!J{dd7P4XSrE;GYR$+uhb0<<~9f z1%FKRTeD@2kx>D0s%HNr@Z0-azumF^>C>l8O-;?s%`Gi0;Quc^US3|lzP<+!9`yJ3 z4-O7Kp63=878V^HjlbnZ0H0gC2$Ve##S^0J{!fwDe~R~hU%co0V(;&%z9&zfOiWBX zQxb3%e5k%>%Y%uf`+j1C{tP~}gTK%Z|HAP9<-ALPIvc~r$Y(u$sFWb`x%sYUmq02~9G%Hw_B0ssDBtNZ@zfcK4z{_ty@VPv$Am1|*SbUV|_ z74&wd04gxT9WkC@WF&uRrt5Iw|LG35bA4zl9UL5l=p|~U=pOr;e?Pq2Ar|3_3e z*26s$5}}QrMK#Vi;pM>ja_$y3v~@^yUF~U?Y;A|)A@iRyMA*&{WP%X`VD{mI3h#UU zBFs}&newUGS8kveZnvwEwkO8XU8`-d_4BY}ku(G7GD#L3dLs><{9P+`XCPD&6$#&! zn_ie2@cwOQuvt)eYh9`(JlWp2(8FG=A_mj2Bo`6-*LHedyO*Nh+T~J41r!-hkNNW- zb6m&UUUfLeKNYf>nlZaERfIv{-ZoM57ld$z<|cCeuvB9W_X*|)@9A&MS=N~1a4X)Z zwbJaJ=YHIN6Q(F_&0f5);eM+2ho#)uTk5*A^#J5DkK_Frl7F`4tU$g)>Ko;yyA&rM zk~5<$FS-mec7ce)zK;qv$q>v@sOeC2V3 z9#k*G@fE0|vUyUjTuFw*@}!~*Tx=6gKG??`*dpy1l0VaA!M{glMN?s~#47Gwq<@zr z%R8urJO#&rA0!LaJI@4EXOO7s|5y^Sa7k*D@H;A_Bo`L#bMpkN5|xKVWb%u=1CfI* zn2MD`yWh`NWi#MMRm=sD%=!Msu3n*n^Glef%Okr~Z6emhg+&y0Nz@#_`9q3uZCAaV ze>799%~Q~Q@Pk>N>8ai?x57iQ42Ky)6_!!s<2ZDAftneHF7g<7n8^>`&{daZ0$Ycd zZITTQwjWjm%;)ZaYj=gvGcIvFcLyIC;K|`HPTO{vkQ6w@-Mo1f=_)LKadVUWf_9lz zHx~Qe(Ag$#Dx=@M;6eibj7F{T%y{%9=?ZimsX)QY0j6!Dw2%VxH4t�(Dl zbEG|OeOH7c9e@-CgifoU<8}VG_qg7!zCO+j=|@i7rKU~%e8sUc=T*&5376~hl#z}+ z(YI6v*#Zvd1X-M9Ea_)~ef};o>ZaDHoPW3k=e1vbX0_tIU%To#Z0l@tIYJXP^CPl{ zpQ0r7vTS@=IX4i=?HcYF8j{t>Q>yH(y?zO6l_#(@N)x`xpL!a>3f*hz# zPCZ6%S({AOo(RSl0{EDKqew#PK!uXTC@&p?8>IG9oZ`q&{b?VSQD@sQQ(4?urlewW zz(Aby4n~1IO(u#&g0(uZQf!_K5U$)cEM7sTL*S!adw;)a$^^{@u zl}6m#*|6#c!)J1=H^rxF(*QlJ3z*2U-cgpRVHBc-4@EH5p6<&5P?oA~6mT1t|0K`aNv#T3V^#tXk3{s- zKf1$&ypRLcOj3x<4)+(2wGaY$ITpq0Vj9=JuEhm{Kl_ge`jnwUb(CAgbr+pDnVhH5vxgiX_C%B}s#zPu^<4&-6)y%DM6#)%6>4McCpDtXeMe=!+Z zE#L0>U9kPLV1zmt{CSCr#H6Bs&O-L7&xS;8Xlj%v<>vcF_Ed4K;e?9*yaSGI$gR_@ zxuUx0inko(*w~dTM1^PV+ z_N};BQEsg%jdl1<{VeTHboq53k4latQXxCpC~sz>spQ3)5um0G)3~SNB6@;PAgx-m zx(O5B$b1UdHQ-C@1!&spki)n$oNO*3Z#y!$Rnbycr(U&(8}J@f7gC#%T`D#a-&}yS z+_D`O-$3>SlrNH_0vU@2REPh_6WQxP0>)(tKk`E%Lv<71bSFz#8N8sv3|n5R=z|`L zc?+N4LY}qcp<1?GY$Ye~uw2vk;9?!7bU-~MMD&PGN=5J@PXJRz&J}3he#aCvUB>iJ z3ML&0P%osa&^Nq!!T9DKNNYpR`>${%B6p?P9u9cU{|>p+D3=knCxwwiwVrVij2a+* z>;ZYfk&KiZxPXo5E5Us29}5f1qh|X+<-Fj%!@~ZAGSfx*bkz-;QjD`Y3#Ygv_O7l7 zs6N5M1vnlxO-U85YC!BG$V4B=vQ?PApqPI~?r{cL!Tq8ERqP#{@4K%j!g{@r&E?q zsx^-C`%-Ssbk9ov7!l8fv!&{H@}e@Vaj(m;w3|!MDnnIpwzP$pyUQ573YSpXH@7=k zLd6yCkIhgl`~E@z(SEgJZ#Z$YmUfOC+2k)$SC$7!((F$JMj(wnjBHN8MgkCUz0-NWGa14V759+W!+PD5I|E7*UUP7C+3ma zU^lBAzF@|QDhtPSg*TGF<0#6*=QlA)&xNsfA&tZYvtp-)*sFb_U7r{{YsoxHeCr5O zM3TH?o@JPMup%61+}ymL{P*Su^2S*A5rysL+2!!^$G?5~mY#f;~@_vKqS z@Z`=?oO*yL>c2oB5yjrF@o_wDhB0>=hwO8Vk&>(a;F`!=&eOKsI;*w(nQH!#rP5u3 zzJ?R5NB;aq(ZBd0eMx^ldx)h8RwrN?)AEKw>+b3hQZ0roVXV$71$t`vI>oh4c~LT# z8Xp+mzg9gU^gJ$QFwN4I}nR$w}R|XTUs(=@Up!(A2<*^S8Y+$bD`nl2VzHV$BQjF zcYqPM-}CQ1sjo0D&0u3IY_CF?)sFsA{34mk_#IQB8v~lRRWWJr2zk(Bi`8Ynbv2VQ zlOtGWUv)_3$O_@jdZ9blhzpkrcktmBGIX0r<&v>J_$du!9lbhMMFHhcJthe1_(>Vo58jzur9*`Mu3}8i6Zm>cy6NX-_Tf~)5&Ke}hSeu@ zb4342Yl2Obo|Lc{5uH%1UPR{8E7;Bf)hVoUDT?jfLw}O%NKoH&SKMM*qusJ(1t=I& zQ>Z!!YA2Rsw^`FS(>yh^M1!>>6bdP*;)I4i!r>u4TWEVov7WS)`;Q$t|3f76s3k8$ za!YNN7x^<5NkcNIJHio_HQ)IL!e^2*m$A4_EII$9zBJ@_`uq~)51lZX&t=FCs~=a% z1Bhj&VRl*J_WRKNnW~+NRW(fNU`5^#Dy;wac&_J$GY=d@;r%083KCl<{n=PJvMbaJ zs`v^c0XVP@Q#ljDqka>9_DsQv=;(7x#fGC}+S5?}P2#USH?ISTh>2A9^vFHB z=~&}=&tvS%tQT{B6bjp@V9{xQL3Tfjn9WhN_5!>>E|mIw4p#+2Wy5kcmaF}bbaCf` zD2_7|4@D~;Y!4~DDAzHFvNOXzW=AHG}7W(w;kkp}Swlb#|zrU#wZ&a#p0{9U*cKq1zt1-OYWP{G4ANbQK-0X#dk+ zF_nY*eEXw}Y|Zu>`D|iTZ6La)!JgY9R|_Xk;w|YOKAFL8RU||qml+T^7>;a3wS4}^ zeAU;*Q0_}3W`9}p(0AqUwW`cAwOc+BN~!l1!I+h0GGDRKzO8~_dl{g@1;>LesQ3HT zjVTjI)CT;r$K{dPWvjyNy-4BEZb?OJp4FW^4?+;`OjmE6`7Qj4ZWTKcGgp@2`Q-x# z?LNf_b1<%QN%5gEN<#U$Z&kRmiugc&BXYExHQW-k58wk0&YaWO6_#c5qp%3MkBcnf z!)R(IpRk`L$RJ}?jm$rZWWTn-R(yZ6a3yZ22stj`*>-4IoIYRmN`K^!e%Gk)@QMR0 zW}0aRgOkCcq9+~iUhY_&{dB;hiTr*LV@L0iA^voQwbNn~q932EACCR?P$X0Yf9C#?4S+EiV;u5v@qMFh$`%PG4@e+9p69m@!W7o5NUW5n{0XJV zw@^U5y2wC&iI&)`b(rtSpPY+ZFX-%!T!%;qj^s4L9OZqPnDaS2 z=Rfah=xsi7VK_!EIjmmx0~zh@P?e9)=*mRXkPiyF>T7zlS=p>|s1%ZFeqm%|8dJ3Q z&UZ;T6pA&r46X53xBvW-%>Gl1oy-6BSGdZv_+5z%nM(*#@7zQc5_0&1t#B>Hlv6OQ za+7iy@vZ6@M-KUumc7S|(Q6M1HY1Yz@_>v;u8jVZ@N)wEgc!vuWGLCi)@H4C2aJ^h zf2}4#A&xKY>=Ot4$!C)Ts_&5@6Aj6^G znjdsSDvrU2Wyg@$=OTesEtwg$IxUC3kbRC|B#RzJRK*T82(TqiHl% zJ2{m~0+56PFM!e}3TexbnphVnJrFc8v|R;|2iDF59+dg>`GNN3*{JfgR2QuFY)0Be zqv6xG6MrkFP&oW+$1tHJMJ^urUAVC|&(vPZa+R-=5Gk*{_4NaihqN25X*Xf06cu#R zxhNMS!a?H+&&0;VKYw9V0-R9K#K2gdd(Z5h+k9|}Uk(mvCm4Rl6ZXvpu3Lx&zFq>n zx7tkb^)^5h8fWlz7EngRIPmp`f_S6nI$HVhfNr1+k`1#yNBgc(3Gx4FXRe_x@8*Y% zDN+hCn?wi3c~E8y6v=~*|33UF=>LA$9@jd)op%*V3pI(o8Z(-dYbzgM%Dem1NhOCR*-Bv4wid5;o)9(Z&H>eC%cYwT2PT6)T#N24>^Kn$<4?lz(R5lI*TyX!8tHld&}RYFY0Sua&=W6h zWjdmHK`yG8DjhgKKRjgY5Oh(SKEzwe8JKI2-Gk*j4a$-&Cm5Yre4)ndG4Qq4=2UG7 ziyJIME}S9-2Q3h4Ln8m~>whsjec@F_9}S-m7kuo=pA}FZ5?3bJ1a2la9k~_n#2J`1 zpXKgecKE9LnpbxEWUh5&3${)z`FjQ{6cHV19Ttbb71K&+%H`W9Gb#5h6NVF*&|)K_ zt#{Bvu8Mu>{I64OJ5*Kig=kB-xr-!h!UU20@tn9J0BZtJ)JCfpZ{F+b9tp*^>% zX#|2JRXw~G50A@1UTJwEVN;)cmr?p98-mKSt`BVDBEO?HWX_V6xBcm^C zzHLk~-6Ac4O7Qm%QjW!OHG-~kNpNJUeDTlif8i>IV?$IWH1U5?ba$b|>g+P|lVkkl z+eh~PXRrxEPtU!KCe0S)lLpcNeSgO`cHB|KYvgC$9`Wr1s{6H)dq+y6n_Z%tY~0Z0 z*;dwQta%i6i?xdmifRBwZTFV2R)&m*Pf$_iYt-MZ@s04<>+2MJ(UhAt0?GFe4;w3K z%~s}7xa#zD=PbCn56cmsl2zb`I!$!sTDt<64TG{H*+(;JE)K_#dZ?j6A&}Q(TMAh_ zvAjUiQnYTesz5MVns85jOaz>@y3SnYVaw!bZ#ZV^=*U zWKQ&r!p`aaNJo$74{QjizQ5kTV0gu_Znvj&73nUYmhLkizkC|Mq8q=L9KVeHKl%px zk53UUdZB0O@|l@d<9ZA!~KF@tY4APtmEN z+jARJjC5c8xc`kWzP@z=J9y~Dm&-r-tjB2PWL<~j%!vy>Za316oqyrCch@br4esr4 z+s+Cot=TSDpZt;fa7( zgAOoDNZVWx)V5&b&p#aLe4F}H}+wHoK2LN8DTO@$v zHVqiaiC+QW=k7D!&%KXF-Aov^+wqU)yQv|rTGxleQ+K;|F={6quLOuXaKiRf1SNjr zL-Zme`r(>y6vX`o0AW=B2k3I($hvSA#7xteYhM+ z6lf>=Vlkh8xMJUgnRymD`v9I-+&25O%**wibv~yjt-FNSZ(dn~h&409rcQV@q;Bmy zpF=-Pm~1Ms=$iA+Diz_D{>Orl%kzSfz> z(BgQ8?oU9=p||hD`+6p64jm2K{F82-Z%yd1?^WMt&ldd?{*DuWgK{$I=?Ss?4;6_?l3j)U zBsG)U9vHurLF=Z?japZU`Jv5Pw}8pNO3VfYjgF7_fi5kYtl^HzyT2UkCg zHdaRVXP|`Y)pg?N!Tn>Q!O5BP)awg+VC0V|SkO-dE1Ndz%6@E2;nk#RZ^)}=^9JVn zr4#E!V~yT*E1t&ta<->?G46gjvr@Ds8$OoH{C<1f7!ZLzad=7B(9n>uCX0EX9{Ki9 zw)cEDgg4Zl>Z%bi+|?#(#`*o)ok+Rdzjcb~@pUtkUa1OAH!N<+My?>Ol@F0qi{|_= z_mBID$Ws&UN#M7hK+M2KoX0B z776VistT3e!l*2SCaAHns$*+YwdBLULTn@-Zx;3Eqy^jVE_$UMki!79UPd2Uv0RG2 zoVb3`d$}vx*Q3Kt>?&=q;_qbP`AT8hsut`|MM^hGO+uUS*MIU#&)GYRd2<(x=$(hh zjs2my)!j@q2Ya$X8`dAL{(a9qOH}+)`97yjD-(HYm5TY0WN0A&+gW z?U5xe%H^Z8q>rnwJu^h{Y(3jaXdYPD@1~fwc1(uRG^U8tx$ReRPv{HbK90l}Qtlj+ z5o*i^+f><*ChoC~8>T$LH2ri(v^uDu&d!7%siWZ0c@uaGvbuWJ6jB&9{2_*c-) zxLq)A7mV8lf7u1MKWt1Pcf%+5-m_FZ7&T~wV%wpX3c4iy+LMjVIax;p9hK{mbveTw zywXtvUW((Lf|`=5;K^xerq~vuBa1M^I!B5#%5Qxch&B>z_m4oFm^=$qd1pIFzbH`l z40m)~#Y+S=4W9cy8mp66o`os#;t|RrAF_qmKIwjKWc_e+zByL=yu)?$aFt`mF>D*M zdsJge)fVX?wVasbw_Sn35#mQVF!civlKk%ov$C&=jmf z8R}=OtPl4XvSZon@=D_7j*4hyu7$W5vk!!67K$|`%F>TX#VCN}(K|HfTA+y+v*dZ* zAU&en+i?TZ2%=+5Do3T4blZ;gY+4W!Ly3=j3bIzv8GmqB>W$qAoO8yF>+x=>muoOX zB2af_c|V9w|+@fJ|BcB?v7&I}<5Dl}%0uAs%%9%perED8A4-?!OSOGp#X&1okCJ z{alyYov}+7twS6$S|{XkKy~`H7%mz_-nK+#@dxG#snx3(|HFtK=F~~=G7lO%9J`op z=}k=UIw~cK)6y_@j`y3im>zmyKlnnoiJTR$g{;j#xtX?N<%{^QDzjV7%LtMq>ia|@ z%y?9>Z}8BIKBI0t(YB+++c~m=L8GlacF_}N9FI{RQm@g435^x~?NIe` zX}pujG}$q304Z`E)eik5{@bq6Y}AeU7Fdtq!lg9=tt6ExFwM^Hh8dAdMzzOkY!6i_ z!9g~*D9T57gu}v<6GpYqw)z{#)Z4Hkec|W^8={Hu-VD#+?_UJ-zmYMvI>WXDJ|Y}$ zMvE@lFmtqRcSbcgpMb-W4YOO@*2v1bR$7#{z-Tlt@al869W?)Bb%Lj_9aF7syFBWc zJ3#dVdnQHOc8*=CzWL=?1G2^B_`t@LR6WDd?YBs4?R)TT4Jq*7S#*<4|B(uJGuI*w z9HTUi_C0Wk*S9_@=L<#CjjJ`<`APb;M$de3JHaFE` z{YaPyl(QHT?i)3Er4NAO=O*kb=x<(+Y@R&UhL&oEu4B-#9@vVV9UqT6;ITZ5v@{e- zF~9o0)B{dUxI3Dez7=a+N^?@jspK6U!rrP3`y3P?l7CMJTFtcWxIL;{Cf6eMfAzPU zc^2I$-%O`|1_l&}(Rz-~rN2Ek3zeu!FfPGy1CVg*s7U)F&%#>Wa4^mG5Py`6u2mq3 zMA#k@cdOqUNlF+s6>2L;(K*Uk)ZYPW8($6`EyDp2Jw3QMr5hGhc8(?0EMy|W0;;AlpS%l`yJb5J)b6hF4>~n&Pd(IE?N;`T|r~5?p)sh;XxPG#UNd1GB*_j8m}s zDbhE(1lsNT*{G=~V56+~q&b%qjOa0We&?w2ZLHD%r@!s+b){$G`%w!=&5~ISD!6Ed zI!e?VDv0hpg~!4y-FQMM+gTWY~?5Ss3KvR6?#Dm1}_dX)#^xA}4xd>~Ym> ztz>jf1@^7Z-n*Kkl{98Ezvio}#^hLk#%KM0NQvUA|8yZoUN)Nd8E6eudRGYY{6VeG zq2@GuRA=ZOP_zeVGz9})6h2lXo!X;rk=}yFpst;bDb`!Uo}g)iG=HAVWDG?GsGZ_} zk)jO|4?iayPaJiJ9+*AWwx(2}RaF_D^!-?nnD=*z_X3}P^kB$PKE9b$ z?`ksNF+eh^fdX_NsIlAC5vD%p#b^1Vs3<&F`=D)9*4VMf)he?vy(*uB-U-hbi}2F; z?kZW9LUjc>Jq9fmfy!fqm=^5E^R0tdL)ZIJlx%VGYL+G;-88}7sI9T z3s#QCJpa>R+10;;0!txM8uT>wiH#VD)zQ`d3$bdguF3=N7)%$XA0AcH0!sp13Dn0R zC1D`HQI#-;Edi7i@T4kWK^}GsdqE3T7%`@%I-iUo98<9?aZzIt)!+^P%pnspP3NMm z9Ni?=>9xR%z=%7??rNmgt(rJGgOKB$`cS?xV;ge9`H!I?B8~{**{Z=&k@M2x8)(Em z;Rnx2rD!FiD+C~Cc!9;q-S*@JpF%YKc~7IshYq7(F#*efmBr-M(^R36gqV;>xx57K zc|`xL_FVeE`MXSJN|52GER8+fZGLUTUC_HTEmBg_`H1dueyROhUD<}eD=Lhn+?p?H zXQ+|nL1X}A&)P291=t21MLy9Qt)l!ZKj?~8oJdGKYFs)f-KjY3x zSU9a)7f^jx%EEf=$S|@&c3oE(@8f_ggMBM7Wkg?lA|uLV`rCB+ zY7tiz2g*;`FsnqBK=R(i9bY}hn!K~&4?~OMk#>mxxLx69^KqP2yykyZIyhnihHsjSRR`|`8xB3)5kznw?CWakHl1fB5-xjaf+Vf zW01=#vAuUyc@nrOtn3m96?LmVeoMHF)V_&MOl(ZaGfl4$ND?TK#!7;`P12Q><%(Nz z_bsL!DIa4pv)=4h1TWZ}8pw!fv>1aFhv;Z=6EQD~Y6@E~7-L=4MU-s#gIkh8H>Bg= z#@jmtY06h<)3sqHvmM$?W+gkd?*R-Ec?s_VUMd;v8mhfhvFxhgwbR30v+wTUb1f#A z%nWIbTNUiYTo5v0R$*d@ZBxp--T&IMG37&D8J#y7d-uUFK-o!9MrZp-fur0vti6D5 zCn*ZzC+>Fr229qN@;!;Knw)U&^^<|^weQutUEj&ISgb3JRNcs;kl?J^C{QJ_rz02X zIq~`~7Tn))92Kx}8xwo^7l+F_xlsZHW7D;m$LP3bh{aRDRd4FZ7ZaR0R+lYB@9zTp zX%w)ryCYUO{0M8YMH-{N`-b6h;OvcOE{!RR0;)l6P5}EJP;ZY0-{>_Z+D)ydu+!YO zNDFc8{|?trwjH3dCs<4#Yl}2g-2)$)8beWbH!;lz538TN!Deqw1dPUTbx%!0&d22G zVy?yOB$>P7qt+_3?T3t&xRE9F#~M476FjQ3fr;t7a)F-4weqC}R@N9BW|lC0o!!(L zspyWrWusL>K>$*hayFfswBU^@8I8YwAUbIL`K@?RniP=5Rq1tqUrotyc&m*YOk5Es zPP!#$y{ZPZz-NTs%numfP*NtCE+^F?r!IW5M~9}2bkdy1jJc1spZ-LA%NF>n*9GLc zrz|nxhmsRh_Ka+ICxtLI<`&+sx|7Njpg3Qm`hw=t#Wb^WvwsXw-?l9V`M>aV}8 z|B>>hfAOx8xC>xt-L&1eCoVg1>8)h0*BAGe<0eF#)vzZXJ@ef;I_&zrb;>^keC2nkLCB07@2MCH67JWcb-87=%-1#q!2GIO4-j6f8xmgw zN+&m{6d-IWD-ZuwEo$?Km^z^}`3vj$I>&(jMJn*EjNQl|oKJysFzv7EQeTdUy?46M ze{FvWa6^-*x27>2b`QhePi{`r(-z1^K~X%^LN+zS^i?h^Iz^W zo~QWE;Xb@ISy#dApA_E!JQyC}xSW%uJ^Ak6i=FdFJg7YeLRmh3ogVXn!%W$G-9IzV zh0}mMxU>948L~|cq`ejAUkKUTnuNay#1kAOqFZOj^+B?&FDix=9GWm|Xyu|gKw9cd z18v0%wgV@36lS=b2$Rh}cyY@GVE*1$$uav1n2sZL))3wZzk%(YH&T17;O>i3XrJ!W zz9RRWTOcw5y=urCUgeYxUA9l9yMBCpte z%;^EQ9eGhq?ZX#E7ZQ#wu_b4p)-`ygkSB9RhBfmne8yhi~FT=oP;=G^S9p zIixv*zpHy9q{BGHvlA~7`)>;^il;rbvhYL~J`V!rm&_N;7=7S#jVWxxl+rz}bbF@c zGCt;fn>DbowPGarN2CyGefNjmgEMAsc~P?OAK22dQ}YpIrHga`mDD$?M`8 z9Abs`19-Mp8VhP5U20Q^>f6AofgSdu`rq8QR$ZryX^NngmjD42=)xn2bKf1Y=ze)Y zRBxjdTm}u^J0gzOwB_z~rIYZ{G-XfEBj0HS@t=+{4Gh-Rf%w_8r zo!1padlLqod~4Hq;LbwQaTT`mB6|2nqBp_Mc8@(KAXZHrz7?Ot%X0%yIaS5)c6~4w z3^|4InqgV?b+on_c>pMAc7xNE(%(1U{ZQw6xNi2k5#Z?uUcZCF+XShpscxJE)^w3< zhR#y|l3iq|LYIX> znGS`d-$5PIF%bo{_+d(Tt5&pI_;ofcaNV!JeF!D|k^*>(OvE|2axK=|5|0Ld{$att zQ^X$EOgZpp`Rkljm-S%@fdAOWLzUpkvt!n3+xA-3xqEnk*9j-rDASk}5@84>JL4fr zADhB-)`W6f*ibENN(_OIbEQ`V^6%3n1G&((2(7BGnGAnDAH-C%%(m~4CU%`)G;_1g zRrGJNaWH~S6QP3f+%JuxILQI2V?K9aDL<0%LAwmcOY(35hb4VmNFoMf-$&c0S8}u= z^;G6JlHnn^iXC}xrK%B);}M41E1T8w?vw>GYdnYyeqRq~0PkcP$$tKy-C7AaJhj+( zAj981Vc2=l!%eJwgU=^*b1Q`&Yg)C#KY66P!R0y_C+dL_s5B8yPDgW8gC+jSXa(w$ zkS-In+)L2j=~RM}c7^z-^mT(r)PJb2>G?0%~FoD05~vu%nLI|>h=$=(ZkEQ z6Sf_A1k2q|@e2g+I%ygi9KwXgE|jjqoqpo!RI|}f3HKWI(ouWymm3t!n1+qg#C7o=S?h3!_io~<__Xaw;C04d7;)%=d?;tFs+5svBF(J>3o|o)D`Wy; zSC+PIgSuEjjB;|gi`Mq5VMr^Si%>@@5;j1|3@Kv>N%;C9^aK+9rwh7Uv~EGv+80F^ z0sBBa=x2r$t7bVrgqk7I{w@go2HdVCv(D@udh{}w8<-_hWz8n!`|2EF?ZWKz1nx<9 z@azE{gi>qwOEEDdq!bC5*M;su_QWeq;qGBaTaS_xpX4td8RpX$>OxD=rfM>f8=x2? zsPouuene|IyP(HnQL-Z_ifFP>f>K?^{lOGpV0%A-Xjspm{J7?i3GhzEp=?-{Lk5dG zW!vE^MgOa~Hjn+@eDz)Rmw4mm=u)p`Wu)W7A<}(nXUZO!TK$EK!`*vISUZ9dq(lcP ze~2UyKXC$Ou1n4*3fz|*81e1xI6G{u_85%PHUZa@6r($ZDM?%JUP(w?DFW3fox|^@ zM`2BD7$eTR1yqxkg@Qg|A4gZYk-XI9!geV$IUvUI8qke=_7`ACpyPBpkjl;PJbMS6 zdY^F{7Tsrp_wRVx`d~Amr;m(Z9wp#LI()9{ywPXV|Pe*-mA#$Km&e zs0)-(>4yh|}){x7w7mqqv*jg7B`IG_#Wq7aqQm2OA zQl-F$M&Kc5?twfRe}(ZMbsoThwhdVpLkilJ+|4a-K-n|5A=$G@53k2u&g*>e(Td;t zS{MC|^?&*bbXwo3T-#`&@gvZL_+PjkB~zo5Gw(=jN4V%A0xZsWbI2 z51bNG`-=pwj1?fR2&7#ohi-D$CA<6bR0=DXK<)KwF>z&T%Ht%D&z{g8HHLPcnY%S2 zcxJ(fsq&@;2c&mhdRMgCYB0$y9pBd6TbngtGJO4N*XiQ(OFaQWmX_c#4$2Z2?}T>je3K>oZ? zWsr0wT=|~#nD5bm($MwOuCJmd?jA9r-!!p7sE#SQd|5{fve-+AYXBzK*9Kq^_zA(o zS&|_^lUC9ROe{?v4t8GxE=m^mBpqb+S;Let zPyM9rZ`?erlyrtL5^bui(aYM-F47O13@oIH>Y-kL6}YDdNSDZlFkSV1X3`>*+OI1| zKV_=S9;;N1X1B(c8^I>Pd@->GFV*WI*<)l23?Dp3&r?E-T>Y?K45-c%pOf`{hYb8^ zfC%z-jbvrazrrm(?h+E!Cp2Jq;Fggu-6-u~ZYP|G&DKA@&b7)} zlZ-)n(7tE%FZL$56|qmSik3=n6tBc99fOp4LykMNOa-vI&< zGauM(-E)9p3{LiMohyrMJL0xS*X9!xuz7d-)7~Jiah-Y1HLY0Z%v58m|~tm6O%3)fa5(NbW)v8y3Dg7q7@!2 zZ|2mXWn=F=h*xU&XPoefA=D!eE*Ze7dt7;u9v?9v>}=kV2X9kzfM(EAy}+=mSPBMH>$&2&5<5dl&> zBeZ~Thy(&R*dU`JEv;KPXRu#Uck#0RnZU*?`rN_>OW_B(Vm~sGL!<{ohwJpCO=m-T zv@j1g2}w6yJPhDR5HN_fgjMx8d_D4~0rcN6a?k7}v`;x}YA>F3fuesgfR917d_^{> zmT&EWu0wE#g7ohv@LJE&uakia%+gEV|I3Z6O5@|u>MSk)q5<66VK#Uj`P?FE_z4mq z-Kp28O!IM7MF^}=YAA@VpBR1)s19LZTkn_+D!QOCPne6FQi$15IL}ZZ=IA$148r;d zuAKMYj_QO@>L;WQv(U#jsA8fEiNJN)ecqrBPi)X-lhNtdddv4+I*mfME;Az9rk&$wL={_kD zGlVo6U@C+CqcG)?$s~gbqcfe*wgjXPcpE@Q^J(gtLB2dRhyFoMsLLfp3txh78)i?S#{G9Ef8~Pb3*TPYM zBOvQB)~d<&E(`FzD5j?&b9c~UVtMF+48~BH>xX(+bmSJ9F<`+b4NFcNpn8A;rOH!0 z+|n)0Fu%z32>{&%0ZJ?a4hYWTjvhSHW&qIvpE{usbE-jXfzB-QuFfKJCrb@*Soj&2 zIzh2T32`pL)Rb;2?~AWI4bxLe-5lqRAQ0jz2Ir%Ey<$JV5j+^KyvcQSZ&}R zH9+ftx+tb=FLrhKA$JG#H{a<4l4zoI*%(=q46x5jL8Pa3N3<5btYd?I@(9&MZ{|>| zNGiAaFvHdWpAL{7+Z5|}N2&h*Q6?J|CqED$(SK3{YNv{gzKED?C+l^sY|ghx((g<0 zGj86dS2r5e2;BK9fo!EfC7Qi7YN&6gXev2n`}Y07}S~zP+5=m z{aL>n1BR+DbR-X=83r^7M10;fv~jJ;7WO4M(bNEMGH`3g01vY7-XYYN1`sefS`D(n zn{Udv;vD3hfeu=y;1676j8z6W55Vrot4y_`gGi16I?OQY08w9Y(4ONwq}_lc2atbr zZt4|72I;K-UZea$vq9N_H*$1}0U8Trn`T>9aqau?;e&MOm`HyYpjAx8s0hdEMga?E z8zSy?ajY%YAA4qEh739>pKDB^az&Dk4q0z{svlR-4U->w>1QYq-jlo6$rmp~tF(Pb zrETxftqgF7)|ow~8x0mfttvp*nR23EuHOCBnHTitwLCeI>JpTxJw=Nt^UL;^WEPX6}9y;SI?%Ec zOY~oOgY!u+;Yiye%xwKEQk!pqcA+_m6e(x#RTwt*9zM?*-KR+T-Jtdu*FAn%k_=aU zKh)O%cycK5ftMfxe3kDyM|x$WexX=odsQYChA)W3I90;(R0pn8>K$t^1$mz(n(Cd}&1a&mk-P{izt6I_a23Q0iHKj;B z9I;!mnKaoP8N(hK`*OSyXi6cQfIQv(z+^?PUQ;!v0K^s^moW?Wu-wxI*;8}$Ug$ms z-stWoq8dIZsL%1}hONI`qkqpp(v~KdkKV)LLt>I4_e=w3p)euE66?Z37WOg>qG}Gg zY863|g+%Yy&s%*ov%w)@+9dki?J|8aEP%OOgmGy+KP*e-XR6;bXH^a^Rx@8vw4M8T zDKpkvzijB$5jDH+i_jrW25J7Sg0Wo&`S-z%r$o}gWSM|_FReGC$<;5kfs=C&+JzqX z#ClQs&W=tEztC5|!VUwBgB-6o6W2$&Xn;x30%R6PZCV9_$PXfhsCVIhV+UlY440k= za<-Uy)M7>arHTsewng+M{d(I1e0 zwVV3D^|y8a+HZh)*$!gzIexIVK6bDx7a|y7!`=cVRx|8R+PGP}XnIJPM7_!i=%G+) z(QXf3TrbJn0H^TLCTOBaI_dm!>#QPva;Ur-E@t7?%YjS=-~{a9kYzFN?!;7Dy}X?W~bd z(z5w#BDD_ff_8|F4OKU{r%upsii3v{>i7%nE2!OY*nAQ;Q%GtCITu^?9{B7*3PgJd zV>ifu^6>Sgi%I?!J*1`RdHQdvbUpiz{2r|p4GgerBTI)Lp>f4Anhq|tR!S6}AJm$7 z9MK=0$pn=(8l8{={7?+VdjS^Z>%w(vb%CYe#-*&sd=BZM{u@c~j6-OQG+1hy?%d(0 zxX#_^5=FGKMhBTgfvDM}Y5EU%>9uB|S=?oHWp3n)T_K8nf_9MRUu1H|Bi;b`vBv&< zb-`X&bD`BdYfuGk_>g{=R;vcw`sC!(i%bZus-JVH=|n40^jG?07=sC*n!z=PK0;_U z6{Ls%s;F1(hND(a83 zN#7cPQ4S#HLjTNQzDN>GIT&uTO6YkIPZQMqqW@%D3f}f`bS<;Lj`7XZO{utMN?Op4 zLS(QuO_wf)T-PN>VPvBuN3lkdqk_O|A4+Ro!kETm$$@&;7wKf?tJ=|WSH-@syr~hm0O{75_%epOY4VS|(K)TS20tP3p$iS0>59+_}Y1`$|4f?HQm!gip~@p&=-y&R~d zo^IU10aNWaE^X5Mds=Hk=5Lc{NL*@tUF$&JkbneF<`TbSz*`FJ7(3!Z6O*KB7&`)C z$OweJqdmVfSAY_Q%hA;~{&%Xq+2f*t$anknt!n9SYv^6>+ilYej@RC0VxkQS> zGp~|6kRWP6%)viEL6hjHqQsD|!A(G>J+r<^d-ANDvkxyqMWL6&^|}Pe@ASLjx+wAC z-qmT~MWK7!*tA|0*kVxASoheCAv6rGnuDg6(&9iynJOWzdkf-RU>J`cHuk5cXhHq7 z0Ddw-Hfc8&l!;XQW)P?PG^RvORmvvM^j&~${81`u>t)CcJuGC z+4DK#8g-;}K)|Mu{K)nu<}&^T>hK}`*Uzor0!eW%Wv`fkQw^)Oe0qAW5&0o-KXaD-!npsyC1XSO4cy#ke zAJAJqXYI6^2TskHlxxvN-nH`q%Ho4>AN@9ETe9t;XA6$*++YQIKSLQaoIC2n#VQQ zxMCl-d&bSeakFsTY92pSjGwv2kEG)#_Hl>CxW8xI9X9SQ9QPKEJ5$Gf&Eu~4@tcbA zi=6R$uJLQY@mtdIOXTrOd&Q<^oHAfm1lt=$vWGsRNJCT`SxX&{Ko$FrHl3U8_c!v#42*` zftqVYM3ggxi)_)VhX={|zv!jI&7eF)Ol$EOOCeMVUh;8?<9g7_;+m~0R7p#1^-c`l zQ6X`_>mar3)yRHh|MVJ)tQX~1&h6D6i2glZFPhGSqOwt;1X=%aV}DeJ4>VMS@7m0m z;rn^Jz9^qGP-|oGCSz@5o7vzos-w5H)#Nq4awOjKjNZVW!(OiP>5VBlsa#Q91uYk4 zDMYuO`$BJ+(+^E4DB;N@*&rDsZgDfXPvzHzE<*GNHo`0@~?Wt#`k$&{DiNf-tJtAL~M`5QQvBe76#6KTx><~9E7c0z4!sUY*ituSrH{^}% zA+V4?v_+asq)KJ0UD&EJ6NGDfY?U>eCVZjcXt zbzYZ<49xlPK+k1Y4LP7!8zfX50{QmECeumpJ$CuXSLwLhRl7@@z7acRB)aT1Q^nQ3 zhrc=z>PGtmu(suDw{g&aE`_QZI{9jTlWxI~?+9qO2xpMo6nv>xd8g|F!p}QB9p)qp`N7R*?=`6p$3HrL9UFN)dsi zEh;JstrH?coDmViAcTTQ$sgvY2o5G2iH8z7NX(<85MGUj29-2J`0c z-u~Ue`HnjC4Tt9YG0nHDnr~M%-_2{j+1dYxz2F84pvQmQkl0q46K@x&6kb zfnHEg;p7%k5sgA|h^(T#Il1o)bPTR{sH0qp<`gSZ_=2oAgH%`L28X6;h_veDy>W(A z)}8+ZEKMBUCj#+}%nlC5ym8gg6c~pbpx*NoJ@ViiQ@;yh?QsnvKj`i7ey7!hh5m2M z!R!;{)(z{@4E$xrPR}t;qv|6V40iD$5D{p=#Bee_--a$9aHip$3?{QKqtel~H0C|% z)-lc8oqk1erDK5uLtLU;J@;7X-;J-6O$Ax|%x916fo{R}9&hv<1LNq7a0Hxs`<=N* z--p&j6**~6vn+BUl(gBI_91lp!Fq@Q9uPL!5H=f#(>T_Wxxt@6gE_^@6mqqIM}s(6 z&V%m4&TJApJ*T>85&`w?h_S-;b0fF)RJnzaMH;m!jG-MqMaNr`fDO<;F5>pmGc2b5 zMzUC0idncn#7QIPm9T%h5N!Hx4g^@<&3JobvT@ir5r;L6tO*XbgKnPr zderGH=BPkVSvA4*rxcjEX`Fcv%&}w5}BQ zC>p97j$-<(F^WWW0Ss;wjYET@ny9p{E_O8q6T!k5MrFILUy{xmev-E;dGWT{5pJ6F zvB|2LnwrfIXRBgI)O`#WEJ`Jk$kJ-SGP=kot;nqngXk)T59X+3QNdw9V>|?8`V%Kj z6v~IPFRa&JQzaQ`u|P z$D5PWe~D>7qEDNMRnJi^QFM4^%4pe$T}(S4lwA1Pb8ONQL<^1UZ+JW1BqtTR zKy@r;bCG)#D4+@b3W=?7K`w&FO}9h)vj^-GjC5Q|qea#|9`*M949icnn9g8EM!iUH z>1pk4)x6^IbWaaf@CmW3%{NbPXPTZfX6S}R zWPAk6httbD{0PXR^^@Dp#Y1Fk&voTl{~kD>D1dJ_KUXDa3jeBWG#(Dl0MbHY-$UR$ z$S@@7RYP3WY^Gt;@C}DEXtl%l=L^(zWJd}brQ_a$TfdO)SBt7#c51jO3}nOiIxv|t z;lPfqUXGfbI7_FIf6wHMhOV=!p~96_8yy`Tz>-?ptRFW$S{O3oNX28V*5QZnh0q9S zjcJ@5O0`5_=h{o*9Tz+nb(>x)neNb;pY`V>SBCmqn^SC!cx??B@mGX@P?vyPp3en0 zyDr6HlRo2kRg?y^&LUMQ!KQ`d^2}zf=Vu3`Sz3I*BDUP~80+?88sUo& z)(Dk|v3dP6J2sJK$97Q=UU9!g>X^uSX2vzkM2Aj2Y^7VC>FQN%h9g>JTO~OO#KhjF z(r1RC8i?kmo|yjR#}d;*bDuw<*WbnVP&ac9T}6S1+insq(y3$iD;s=D?U0x$JTNqr zj9PX2y&BLG9`N#$vOL|$8K{(_S&y0OJPlmltZ+)ilLe}y*Ndy_CPz0Yl0fssMzpEF znN-Mo8{)MTTfVW7v5?4KOW2o*+*A$RHuGoFQJ>=i5N`?Hml?bZ$FFE()A27z-!B#B zev?6?8i~CgsOgcu@pc|H@SJ>k1jNnJ*e&G#YC+uJAB-q2Psj>=wWGWEq9x5!xJzq{ z_r#B6a%pB_ji{mFixzHN;9#b{FB9$mC^Bi5Zhg?-C}@us`_qQt`J~^bV{C@4zq|}S#DCX}g?f*q`V7KZEEyLxo7%|CXlKQ=7i4m3sIEHh zI}XBJ($`AU8J*8`6+GaCz41U&r5hOcnZYTsFYdUY#0?c}nmG)SZ=huFfhml3>lSOJ zc4Y!M{laXA`U{Tx2I*?l>W}$&up#NUqQ{=4RJ(ZM^Svmi zT3vbqbgt^T9M8{y0}7NwXs`%Z0@TU_!cyP6cn4YwhRSFT9}Ie%I9(=}Y=CPBHE9 z7@H+Xm^Gm*uNh0L>WfiSpRujz@0}?`tq*Rq`^=0BlDDph=y~|V3_FzwotE*3=NudD z?o@vzG*r38s`qMU9~I%JRPMZeC+&@P5JOw}2yyg114M;qA=f{C2Eih&9&g@x$gi0pIj0e@ws8^zJl zQARVx2%@~NsZ;HvSr>4UKVHPNPlo1S2bwbKIofh6{)*CdE$+}Wydbw6w{5f=@(J&u zT$w&GsP$ymA=S-)K&=PDyd^t`=!h2jZj3}T-WWI$$jH#TGsU}%U)xf!zE3UBS)jJ{ z7n*>PCgdHI;}`MU&ynhZ%Va~~xD>}J+x=B9qE6x6IcKC zti`P>9^!`sTOc<0^q620%gUH4K83q8xr_0W`5YBGR99!T_@n;PrZg|?nEm`Go|9%) zLCMM@g9|EtyG%lvW$cT^<9oX zE@$Q(1hmzqY`sB(73S&`5(BM^wMmeR@_Y!@E&BT@!V)dardfhD&091UT5A{V2zJIA zs=OgrMsbh&UefhxLQx8qkVY(Iq718L2Ocn%U>>E=;2?Lbb#pwt+;^RPa{RkX`U5>y zdSp>6n&!4LsI?&3enNH2`aoq%m8aS_Pm#Nsp|0=mPTV{?jAC2Urp+NEU5t!@SD1s; z(V|>crJK9(nm#k)K;aQ*h;^1b^elNW>N!@6+MB9xv8|=LR=bBCgOF^5#Qhs0yd3}G zl{FHx|B98aWM9D_lB0n$G&ghG_31m$ABq!hZ#k(-yEcBM5li%o?P%zmW|4m_Xz-vQ z%%h){)7Xv4Gvne<@>U3QBg-9x9~9rVhV^GRLwp1;_}XFhDw7j;A#lg*MhiexZ2w<40wI~1u_W2F`(QQQYXZ_pzYbb!ddvfL8S4?_H%2f< z=xeE;lrNN?&G0O>-6`D~tBbeC`3(+Q-{vgw-U$hP^Pj$JOz{vs0(2MP1LZyXEv)2N z$P6Bs5au3M!H3F(*5(Sm3W-i9HH!RD61hW7y=`ppRk3n2dvlW6t+}c+^vw2B)czX{ zgLDAk@g^=1*9K`?wi}`=q8cwLk3mJoOBOZyZt=y(b$ONw&D+VJiWwQD=bm}})UW_N zk2>BZ0>_k{MqCEvBPK^!Z@#rG(;L#3dW!Wds|olhHKSqcQGe6!4xH&Fq`lfC6S`SB zwHf~fHwzN{(`ZQc3QjBzO$%fjnqp2%cPaHkEfuJ*>(m>d67mCgg}LlYrwH&X&i>`LwD|2CZ>=o8JxJwTS1)58hS5UE zBs4{$vIk-)8^2Uy{y`LqVbJz($N~ zwcF#%6SQ#Z$ajA{rb@$D%Ra~T53pE&*-n+Geq0NYNU|o9<_Zq^ucv+fy z&~OC!9b^0c5$d|1%h!7dJ%0#p#YHY_KZ0?(>ZtYA4pC6_MaC<5Y4XG6r1wE~7}a7t*KA;)SD?6yZb5)r zw;um1>5v12MObh(aMbjuUKg=7rX6L7#U*6vy|DeZf@xy58C9BB=ggle(hUOd6&C_6 zO|#F)qF)SuC?n_X#7ZaLIG;Vv~#CZv%P zjB+jo`S;<+i@lT&Yp&)z)@v|dEzsWWB%BIqz8VDQVD@Py89a6t8m_i z^QV1~e_JI#`uRQjZdc^iXx^ zhsaM^Dtaa60m5{tr0k1Ur^FXArbCJpKT=PdRwj*j0k^C=Q9Y;&YxKSP3^4`2#Fz{m z@5{`}!h+u*wczXy&T+pgF39l;es`k$tRVXBuE#Q^)$}?{DcxZM@m4;IQL}3x3ZU?zaO3XHk_KU)ruh4*l=C!8chRkOpq6BY7~&_f@at%Vbq(E&lPX zTVD&^j}cW4f2IVxTE|^uUCawJppWVCcuH88v&w;*Q%yZT^Q~$3-E`^8zxiHXfHBI! zCM48nxJYlDu=k$y*Dc&2u+HpUx10h*MS)`FR=slZ(f2V*>8iC?w~ z&PTJh+6plryF$m+TSt5+P>+<8kB#MosKc%%{e(pa9YW|Bijf%%GDPHB%W>Dp>FQ<{ zP9iCyvi7M{5-9T6Foo^s$LrvK({*R26mpGFSJJx>`>KQ~hyjRrz^c(1Da-7Bby(>0 zR1U?C9u4_#oAMN*oKgLL{F#|x@6U&hU#72-a=G7}VEfLl7A`>mf`NgD1Yg_lp0V+b@7(jrTVRKA4L+I-i`s{5Nb2J>!$%q)NvHFvz07et0Ge z3C2Q!Xqk#b3$eHxg_42Z60vejW?BGy@G}&~erkMnPTwFy3)k5WyvJ^ag9g%36byFc zeg^E@O%#6qucVVLY+?e*8p}$}94iQe!c=l7{JR(;z#VBVwWi(&hqD^RqB@dVZMqWe zJE-UqWO27k2ITtXP;B~NBTsvWPoLP(hmsUdrI@p3X0tp`Susmt_m0^wxVV2%cbmi} zJtLsZ4%?hG@afJ4-!7kny@Q{3_=SW9-#aIm^LO-rB0>N<5Y#nF+FW5=Mqa?PaJVj?>Tw*R>>o1sp@O z26mA%7p}gf#Xe~=q(1CrxGU;9`zl2JwiDjG3HgllWB$^k2B{pR0h$Dxx-P+QmXtVi zNe?_Jum)0+N^?+g)q_*$;mHo3sO)pgQ%7Dv1>G#K2D`n4B+x+Nxx0$3f|S-e-HDII zO=!*_)gz>s-5gGX!7Lxot*u>nxKQO28NZ1++@=(#NojRrWiO2`Z(!sNzZ1_Hu$rO* zmjk}+jfW(Tf~e^A!1fqRgf=1U?R>|kqrNTPlOK?zWO-&*$;s7#wzJ5VCJB}vWk%AJ zLJ7%zINMy~;o0fOKd=C1Sqo9>i!owFCr!W$U{8r=>%cWOuR|=vLYirLjEe2;`ka69 zTq~2v#`VyQ6`rTO_1)XyHq!t{TOyP3DG|s08b1Q0=_PKw5SA`LGGLUGT1UZK*>Z`v znqv%l$0nIuYsnc$d~B2Y-X|s+>~3^Nz3$a>$2%OH0!fDNBoc8;1EMJqh#~7Yx24xWCKtB zUC!KWP=tb%L>9Q08&t3KCb{Y}b^?NnSq_`Fn`6UV!4PJT?k5$CEb*nCz||VqI>TSq zS<`MY=yI3XZF}zF7vUi`@jOqZ?(gX4f~Qk3ITtKx{onismf_hNFs7YKOezPJrVI}Wv5+&ntFmc9YbFy^YgvW%>;5e7BV%9tSi#gk6f&vV> zB_%%bhjyE_*^SF#o9m#^-Rfi+dGa6H%|TJ@Tnji^6gq>rsns9^UsQ@HGjG8x$T^8F zr5k+^^&&s-)E#%E4<00}!NgI1vie??KKirDjxGePPS24p9BuYLtTu-h&oj0bHeD#e zjvhvt*JV^;=~ejb422D zGPz-y*1B^AUG)i@88O@GoE^aX7I1BwmOFw98?>E;FdzR}0)0?a4DGaA2CW{81`KUf zLJ}QqnyioDpuOWbTB4V7C$K{T?WYdGUmFe6@vCB<$p2lc>jwAzI@ylG0bj5MjyS?I z`0>6)y&s>nb!<|Xm~#N&sv8t&5A?VJYJ?TwrL#ToL*r~4o&OiAJ_CsAi>!YA#mrXAEYH;!`9uwfw>-#%fD*n&j$ zp+ZiE?#q{*A*g^URka%rpNDEeUe(CWa^2wp!wpJax!(QIDswuf8dpPjfoav9@FYx3 zw?z~d(-=WEtts{`n03)>TPiZ;5Xz&X$oY%SQ32~!i`jURRSH&|&TLW|p(%M?35j~W zB^hWmS(D?;r2F_3(xA;;58^n@8QQwi6b3~`MR*JvP>L?MD`%jO*aIC{Oc$T3lxPTA zKBqZP4~2`o0WlTLVP~3#DLHZBVaOmfJqBr*dFHC1xWXQw9ziy-l@R7+$S#-5JFVdo zGDbE2p%qX0DT~NQS4R1Qubevu>v;M@B&@x$xo~gtC@t77CcpE~MUe98)H#YJ4oc!a;Ae#7rU@P5*B1}4cS{~_eukdZpIJHEhioud zOuJW8K+n5>;a1?Sy5kuVty52^m?Ws_8%oT~Xz=0$o&_8{YlS$v$l%T>? zZ#%ho!Nu2*zeB`hNh$hC%j4lZ8UiuMLHhXM@iPZ6kMoR1Q|Yft&}h^>?G7iT;#2e% zFm?a)R&z)c0;R3C8Z89BWeKwZ17MRGr?&1hKSvCTNeYhXsftgfvP>(O-(U=8$v{gS z0oRAzL~;(8n>~aoqLcKd!nJS1tRFyX@6UTfO-o?MoFUbE@g5{tLk}S-fZaO*t={f2 zgxWj5Li)pX$=t}VAeyIc{J#$TD$VX=*n`iZcR;`MSE0wCOn|oe%Xw`4&oINWNQxsI z6;Vk6g!HWObKsCG3gICP#8Vtm!oaU6j#Nnm0gY-(Nmd)dR%ky-qGJK5OfN$YuLPx= zgagZA7gs=RzISp`JQ1hX&ZKop%xaU`YG5{5{rGygDkTboxn~sWhnuhj3>=6+1QH@S zlM@WxugaMj-BSnoa?Y^E(qZ-TGdIN@rWxS$gONlLx`)&YHJglPF;g#SH^Gi2K?1a~ zTqXa$y9n&;&hG6k&e=A?i==ciU)p?tw&pPwq)l)7oWv zo~y(cJtE8Ef~dzC>MDhsJ8#>`NPnbCSU%1KAIi6Uhh#F4HB*4BuGEcV#~#0GAbNMl)On5tn$uNmUrd-k z^j(YR3uQeBQ-w-@penLaf=~LjuPQ~+nbFObx`P~u8FL*Vt{_*bo^xhrc zh~99{8dJHxK%$~;dsfXJ+-M4n+YqyS4kL5c&sZ75tOv4 zX}39kL*0$f?VWc5x7)1VEA>!jTwh<0K1vycmWaP6E%kZPz)q^m|#ef_~Rk7upbV6pD-zrCN) zGR5DI9`JL~%$h<6iRnl75HVJsXQoL;EiTewO(I2*fC4tq+<0axqS%Eq69BN=A67UZ z`g7_5dkIz1!`o+szNsY+RaToXymmC_OWzic0q|Le*xRJmrv}#UhxpFDJ!4G8vtF@ZT1pFv)dDH1*P8aKbi1Nw&1e zY&sPC(-Cy?J&vJGoL4krUxN0oUeATwZX_$VHj?y5fZN9Vd&3(GSV)v~m*}?XM<|&< zU_DrA{oEZe{LB)XXnsdRZ=>Iaye&Bubk>Bu1U`C{{#G9Y86j-ZR*sXXKiWZ2oJ~6?qIxH2eXkIEl$cLzk%rrxmoG|m(;c5e{xv3&DrRlvkiKuj9C@wp zRA(hz>yDobD)bL`GcT=IU555=-Q{VNN&fc^B(;VJ$CH|BwU}*bk&9r*eEy4NMGfG{ zII)!?L%LAod*3(Du&D!;u3+aP74qh4XrjfjQ08h%zy>R#>a_%6r|4O&hs>MZAFi8K zHXM4Ty{8HgW)e-IXCCJDi5lj%S@sC;|E%-cWf7P7z+evlZB0js96u=i;K(-Q#_5_6 zMF@Q@fD1B|s9#h`v2(3gL#srO-vK=@aMRZS(XW-HpTO{|gE@=1*gLJS@<((7o3J9M z$igI|b6G0h?e1zOv`<_9=RjO6h<$f4xw z{~%17Ss29=U50w@lJy1DN=%ql9u`b~LNjSPoS8)8iA1o=CIw4|QI4u+&fg+tfO)fvP0OhU>fzaLl)V ztQw|oIA!|_$l`GoLd75zn0Eu zI;zj@?KD#zOckdhsOox?x1~7GD{wiK@nqD+MT1!Z9ANzzR*);zR>aT*TX?3Jx8X0* zen&~7hg;ONe0naL_0qOmu|M^P)86mZVx5@rkgqkD*Sqm9oTktGs+f5dJ*EevMV4nm!+Tlu5K_X-t3S+knlm7i2s%4YS!e@jin^JtNUtG1GS+Qx4a8Bqb5 zn@H@iuD|>J@K|u4@5*9Z;*drciar{|AFPyYgAKXOd0$UR;cs)lv$pY5W3E`5?iaDN zqu=Y+t1D6!m%}5cx3OTkZ$lCbB{FA2qoLo+IgfMx@_!r~FI!%t|3QY82hbzuC~+~? oLa{wgo7<^@HBQ@1D64J3iDaRNEpVW2?%wVlLEEdpKlbzg0*hTlM*si- literal 0 HcmV?d00001 diff --git a/docs/performance.md b/docs/performance.md new file mode 100644 index 000000000..77fa625a6 --- /dev/null +++ b/docs/performance.md @@ -0,0 +1,87 @@ +# Performance Test + +Workflow-core version 3.7.0 was put under test to evaluate its performance. The setup used was single node with the default MemoryPersistenceProvider persistence provider. + +## Methodology + +- Test Environment - Test were run on following two environments one after the other to see how workflow-core performance with a lower vs higher hardware configuration. + - Lower configuration + - Cores: 8 vCPU ([Standard_D8s_v3](https://learn.microsoft.com/azure/virtual-machines/dv3-dsv3-series)) + - RAM: 32 GB + - OS: Linux Ubuntu 20.04 + - dotNet 6 + - Higher configuration + - Cores: 32 vCPU ([Standard_D32as_v4](https://learn.microsoft.com/azure/virtual-machines/dav4-dasv4-series)) + - RAM: 128 GB + - OS: Linux Ubuntu 20.04 + - dotNet 6 +- Test Workflow: Workflow consist of 3 basic steps. These 3 simple steps were chosen to test the performance of the workflow engine with minimal yet sufficient complexity and to avoid any external dependencies. + - Step1 : Generate a [random number](https://learn.microsoft.com/dotnet/api/system.random?view=net-6.0) between 1 to 10 and print it on standard output. + - Step2 : [Conditional step](https://github.com/danielgerlag/workflow-core/blob/master/docs/control-structures.md) + - Step 2.1: If value generate in step1 is > 5 then print it on standard output. + - Step 2.2: If value generate in step1 is <= 5 then print it on standard output. + - Step3: Prints a good bye message on standard output. +- Test tools: + - [NBomber](https://nbomber.com/docs/getting-started/overview/) was used as performance testing framework with C# console app as base. + +- Test scenarios: + - Each type of test run executed for 20 minutes. + - NBomber Load Simulation of type [KeepConstant](https://nbomber.com/docs/using-nbomber/basic-api/load-simulation#keep-constant) copies was used. This type of simulation keep a constant amount of Scenario copies(instances) for a specific period. + - Concurrent copies [1,2,3,4,5,6,7,8,10,12,14,16,32,64,128,256,512,1024] were tested. + - For example if we take Concurrent copies=4 and Duration=20 minutes this means that NBomber will ensure that we have 4 instance of Test Workflow running in parallel for 20 minutes. + +## Results + +- Workflow per seconds - Below tables shows how many workflows we are able to execute per second on two different environment with increasing number of concurrent copies. + +| **Concurrent Copies** | **8 vCPU** | **32 vCPU** | +| :-------------------: | :--------: | :---------: | +| **1** | 300.6 | 504.7 | +| **2** | 310.3 | 513.1 | +| **3** | 309.6 | 519.3 | +| **4** | 314.7 | 521.3 | +| **5** | 312.4 | 519.0 | +| **6** | 314.7 | 517.7 | +| **7** | 318.9 | 516.7 | +| **8** | 318.4 | 517.5 | +| **10** | 322.6 | 517.1 | +| **12** | 319.7 | 517.6 | +| **14** | 322.4 | 518.1 | +| **16** | 327.0 | 515.5 | +| **32** | 327.7 | 515.8 | +| **64** | 330.7 | 523.7 | +| **128** | 332.8 | 526.9 | +| **256** | 332.8 | 529.1 | +| **512** | 332.8 | 529.1 | +| **1024** | 341.3 | 529.1 | + +![Workflows Per Second](./images/performance-test-workflows-per-second.png) + +- Latency - Shows Mean, P99 and P50 latency in milliseconds on two different environment with increasing number of concurrent copies. + +| **Concurrent Copies** | **Mean 8 vCPU** | **Mean 32 vCPU** | **P.99 8 vCPU** | **P.99 32 vCPU** | **P.50 8 vCPU** | **P.50 32 vCPU** | +| :-------------------: | :-------------: | :--------------: | :-------------: | :--------------: | :-------------: | :--------------: | +| **1** | 3.32 | 1.98 | 12.67 | 2.49 | 3.13 | 1.85 | +| **2** | 6.43 | 3.89 | 19.96 | 5.67 | 6.17 | 3.65 | +| **3** | 9.67 | 5.77 | 24.96 | 8.2 | 9.14 | 5.46 | +| **4** | 12.7 | 7.76 | 27.44 | 13.57 | 12.02 | 7.22 | +| **5** | 15.99 | 9.63 | 34.59 | 41.89 | 15.14 | 9.08 | +| **6** | 19.05 | 11.58 | 38.69 | 45.92 | 18.02 | 10.93 | +| **7** | 21.94 | 13.54 | 42.18 | 48.9 | 20.72 | 12.66 | +| **8** | 25.11 | 15.45 | 44.35 | 51.04 | 23.92 | 14.54 | +| **10** | 30.98 | 19.33 | 52.29 | 56.64 | 29.31 | 18.21 | +| **12** | 37.52 | 23.18 | 59.2 | 63.33 | 35.42 | 21.82 | +| **14** | 43.44 | 27.01 | 67.33 | 67.58 | 41.28 | 25.55 | +| **16** | 48.93 | 31.03 | 72.06 | 72.77 | 46.11 | 28.93 | +| **32** | 97.65 | 62.03 | 130.05 | 104.96 | 94.91 | 58.02 | +| **64** | 193.53 | 122.24 | 235.14 | 168.45 | 191.49 | 115.26 | +| **128** | 384.63 | 243.74 | 449.79 | 294.65 | 379.65 | 236.67 | +| **256** | 769.13 | 486.82 | 834.07 | 561.66 | 766.46 | 498.22 | +| **512** | 1538.29 | 968.02 | 1725.44 | 1052.67 | 1542.14 | 962.05 | +| **1024** | 2999.36 | 1935.32 | 3219.46 | 2072.57 | 3086.34 | 1935.36 | + +![Latency](./images/performance-test-workflows-latency.png) + +## References + +- [NBomber](https://nbomber.com/docs/getting-started/overview/) From 406f4869527d95d8f6ff1cdfd61befc53f038b93 Mon Sep 17 00:00:00 2001 From: Stuart McKenzie Date: Fri, 28 Apr 2023 11:30:47 +1000 Subject: [PATCH 259/342] remove nulls from constructors and dry up the service extensions --- .../ServiceCollectionExtensions.cs | 37 ++++++++++++------- .../Services/DynamoDbProvisioner.cs | 4 +- .../Services/DynamoLockProvider.cs | 4 +- .../Services/DynamoPersistenceProvider.cs | 4 +- .../Services/KinesisProvider.cs | 4 +- .../Services/KinesisStreamConsumer.cs | 4 +- .../Services/KinesisTracker.cs | 4 +- .../Services/SQSQueueProvider.cs | 4 +- .../DynamoPersistenceProviderFixture.cs | 5 ++- 9 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs index 171860524..5d62bf3dc 100644 --- a/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs @@ -1,6 +1,7 @@ using System; using Amazon; using Amazon.DynamoDBv2; +using Amazon.Kinesis; using Amazon.Runtime; using Amazon.SQS; using Microsoft.Extensions.Logging; @@ -15,47 +16,55 @@ public static class ServiceCollectionExtensions { public static WorkflowOptions UseAwsSimpleQueueService(this WorkflowOptions options, AWSCredentials credentials, AmazonSQSConfig config, string queuesPrefix = "workflowcore") { - options.UseQueueProvider(sp => new SQSQueueProvider(credentials, config, null, sp.GetService(), queuesPrefix)); - return options; + var sqsClient = new AmazonSQSClient(credentials, config); + return UseAwsSimpleQueueServiceWithProvisionedClient(options, sqsClient, queuesPrefix); } public static WorkflowOptions UseAwsSimpleQueueServiceWithProvisionedClient(this WorkflowOptions options, AmazonSQSClient sqsClient, string queuesPrefix = "workflowcore") { - options.UseQueueProvider(sp => new SQSQueueProvider(null, null, sqsClient, sp.GetService(), queuesPrefix)); + options.UseQueueProvider(sp => new SQSQueueProvider(sqsClient, sp.GetService(), queuesPrefix)); return options; } public static WorkflowOptions UseAwsDynamoLocking(this WorkflowOptions options, AWSCredentials credentials, AmazonDynamoDBConfig config, string tableName) { - options.UseDistributedLockManager(sp => new DynamoLockProvider(credentials, config, null, tableName, sp.GetService(), sp.GetService())); - return options; + var dbClient = new AmazonDynamoDBClient(credentials, config); + return UseAwsDynamoLockingWithProvisionedClient(options, dbClient, tableName); } public static WorkflowOptions UseAwsDynamoLockingWithProvisionedClient (this WorkflowOptions options, AmazonDynamoDBClient dynamoClient, string tableName) { - options.UseDistributedLockManager(sp => new DynamoLockProvider(null, null, dynamoClient, tableName, sp.GetService(), sp.GetService())); + options.UseDistributedLockManager(sp => new DynamoLockProvider(dynamoClient, tableName, sp.GetService(), sp.GetService())); return options; } public static WorkflowOptions UseAwsDynamoPersistence(this WorkflowOptions options, AWSCredentials credentials, AmazonDynamoDBConfig config, string tablePrefix) { - options.Services.AddTransient(sp => new DynamoDbProvisioner(credentials, config, null, tablePrefix, sp.GetService())); - options.UsePersistence(sp => new DynamoPersistenceProvider(credentials, config, null, sp.GetService(), tablePrefix, sp.GetService())); - return options; + var dbClient = new AmazonDynamoDBClient(credentials, config); + return UseAwsDynamoPersistenceWithProvisionedClient(options, dbClient, tablePrefix); } public static WorkflowOptions UseAwsDynamoPersistenceWithProvisionedClient(this WorkflowOptions options, AmazonDynamoDBClient dynamoClient, string tablePrefix) { - options.Services.AddTransient(sp => new DynamoDbProvisioner(null, null, dynamoClient, tablePrefix, sp.GetService())); - options.UsePersistence(sp => new DynamoPersistenceProvider(null, null, dynamoClient, sp.GetService(), tablePrefix, sp.GetService())); + options.Services.AddTransient(sp => new DynamoDbProvisioner(dynamoClient, tablePrefix, sp.GetService())); + options.UsePersistence(sp => new DynamoPersistenceProvider(dynamoClient, sp.GetService(), tablePrefix, sp.GetService())); return options; } public static WorkflowOptions UseAwsKinesis(this WorkflowOptions options, AWSCredentials credentials, RegionEndpoint region, string appName, string streamName) { - options.Services.AddTransient(sp => new KinesisTracker(credentials, region, "workflowcore_kinesis", sp.GetService())); - options.Services.AddTransient(sp => new KinesisStreamConsumer(credentials, region, sp.GetService(), sp.GetService(), sp.GetService(), sp.GetService())); - options.UseEventHub(sp => new KinesisProvider(credentials, region, appName, streamName, sp.GetService(), sp.GetService())); + var kinesisClient = new AmazonKinesisClient(credentials, region); + var dynamoClient = new AmazonDynamoDBClient(credentials, region); + + return UseAwsKinesisWithProvisionedClients(options, kinesisClient, dynamoClient,appName, streamName); + + } + + public static WorkflowOptions UseAwsKinesisWithProvisionedClients(this WorkflowOptions options, AmazonKinesisClient kinesisClient, AmazonDynamoDBClient dynamoDbClient, string appName, string streamName) + { + options.Services.AddTransient(sp => new KinesisTracker(dynamoDbClient, "workflowcore_kinesis", sp.GetService())); + options.Services.AddTransient(sp => new KinesisStreamConsumer(kinesisClient, sp.GetService(), sp.GetService(), sp.GetService(), sp.GetService())); + options.UseEventHub(sp => new KinesisProvider(kinesisClient, appName, streamName, sp.GetService(), sp.GetService())); return options; } } diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs index 6d3c712b7..887d11a7a 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoDbProvisioner.cs @@ -15,10 +15,10 @@ public class DynamoDbProvisioner : IDynamoDbProvisioner private readonly IAmazonDynamoDB _client; private readonly string _tablePrefix; - public DynamoDbProvisioner(AWSCredentials credentials, AmazonDynamoDBConfig config, AmazonDynamoDBClient dynamoDBClient, string tablePrefix, ILoggerFactory logFactory) + public DynamoDbProvisioner(AmazonDynamoDBClient dynamoDBClient, string tablePrefix, ILoggerFactory logFactory) { _logger = logFactory.CreateLogger(); - _client = dynamoDBClient ?? new AmazonDynamoDBClient(credentials, config); + _client = dynamoDBClient; _tablePrefix = tablePrefix; } diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs index 32ebe488b..0863f1393 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoLockProvider.cs @@ -25,10 +25,10 @@ public class DynamoLockProvider : IDistributedLockProvider private readonly AutoResetEvent _mutex = new AutoResetEvent(true); private readonly IDateTimeProvider _dateTimeProvider; - public DynamoLockProvider(AWSCredentials credentials, AmazonDynamoDBConfig config, AmazonDynamoDBClient dynamoDBClient, string tableName, ILoggerFactory logFactory, IDateTimeProvider dateTimeProvider) + public DynamoLockProvider(AmazonDynamoDBClient dynamoDBClient, string tableName, ILoggerFactory logFactory, IDateTimeProvider dateTimeProvider) { _logger = logFactory.CreateLogger(); - _client = dynamoDBClient ?? new AmazonDynamoDBClient(credentials, config); + _client = dynamoDBClient; _localLocks = new List(); _tableName = tableName; _nodeId = Guid.NewGuid().ToString(); diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs index 0c78c6048..01beaaabe 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/DynamoPersistenceProvider.cs @@ -26,10 +26,10 @@ public class DynamoPersistenceProvider : IPersistenceProvider public bool SupportsScheduledCommands => false; - public DynamoPersistenceProvider(AWSCredentials credentials, AmazonDynamoDBConfig config, AmazonDynamoDBClient dynamoDBClient, IDynamoDbProvisioner provisioner, string tablePrefix, ILoggerFactory logFactory) + public DynamoPersistenceProvider(AmazonDynamoDBClient dynamoDBClient, IDynamoDbProvisioner provisioner, string tablePrefix, ILoggerFactory logFactory) { _logger = logFactory.CreateLogger(); - _client = dynamoDBClient ?? new AmazonDynamoDBClient(credentials, config); + _client = dynamoDBClient; _tablePrefix = tablePrefix; _provisioner = provisioner; } diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisProvider.cs index 99d43d94f..d8aa519bd 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisProvider.cs @@ -26,7 +26,7 @@ public class KinesisProvider : ILifeCycleEventHub private readonly int _defaultShardCount = 1; private bool _started = false; - public KinesisProvider(AWSCredentials credentials, RegionEndpoint region, string appName, string streamName, IKinesisStreamConsumer consumer, ILoggerFactory logFactory) + public KinesisProvider(AmazonKinesisClient kinesisClient, string appName, string streamName, IKinesisStreamConsumer consumer, ILoggerFactory logFactory) { _logger = logFactory.CreateLogger(GetType()); _appName = appName; @@ -34,7 +34,7 @@ public KinesisProvider(AWSCredentials credentials, RegionEndpoint region, string _consumer = consumer; _serializer = new JsonSerializer(); _serializer.TypeNameHandling = TypeNameHandling.All; - _client = new AmazonKinesisClient(credentials, region); + _client = kinesisClient; } public async Task PublishNotification(LifeCycleEvent evt) diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisStreamConsumer.cs b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisStreamConsumer.cs index 799125a0d..5c89f7837 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisStreamConsumer.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisStreamConsumer.cs @@ -25,12 +25,12 @@ public class KinesisStreamConsumer : IKinesisStreamConsumer, IDisposable private ICollection _subscribers = new HashSet(); private readonly IDateTimeProvider _dateTimeProvider; - public KinesisStreamConsumer(AWSCredentials credentials, RegionEndpoint region, IKinesisTracker tracker, IDistributedLockProvider lockManager, ILoggerFactory logFactory, IDateTimeProvider dateTimeProvider) + public KinesisStreamConsumer(AmazonKinesisClient kinesisClient, IKinesisTracker tracker, IDistributedLockProvider lockManager, ILoggerFactory logFactory, IDateTimeProvider dateTimeProvider) { _logger = logFactory.CreateLogger(GetType()); _tracker = tracker; _lockManager = lockManager; - _client = new AmazonKinesisClient(credentials, region); + _client = kinesisClient; _processTask = new Task(Process); _processTask.Start(); _dateTimeProvider = dateTimeProvider; diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisTracker.cs b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisTracker.cs index 9c5548420..d7c028c46 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/KinesisTracker.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/KinesisTracker.cs @@ -17,10 +17,10 @@ public class KinesisTracker : IKinesisTracker private readonly string _tableName; private bool _tableConfirmed = false; - public KinesisTracker(AWSCredentials credentials, RegionEndpoint region, string tableName, ILoggerFactory logFactory) + public KinesisTracker(AmazonDynamoDBClient client, string tableName, ILoggerFactory logFactory) { _logger = logFactory.CreateLogger(GetType()); - _client = new AmazonDynamoDBClient(credentials, region); + _client = client; _tableName = tableName; } diff --git a/src/providers/WorkflowCore.Providers.AWS/Services/SQSQueueProvider.cs b/src/providers/WorkflowCore.Providers.AWS/Services/SQSQueueProvider.cs index af2c40b20..c15fb02af 100644 --- a/src/providers/WorkflowCore.Providers.AWS/Services/SQSQueueProvider.cs +++ b/src/providers/WorkflowCore.Providers.AWS/Services/SQSQueueProvider.cs @@ -21,10 +21,10 @@ public class SQSQueueProvider : IQueueProvider public bool IsDequeueBlocking => true; - public SQSQueueProvider(AWSCredentials credentials, AmazonSQSConfig config, AmazonSQSClient sqsClient, ILoggerFactory logFactory, string queuesPrefix) + public SQSQueueProvider(AmazonSQSClient sqsClient, ILoggerFactory logFactory, string queuesPrefix) { _logger = logFactory.CreateLogger(); - _client = sqsClient ?? new AmazonSQSClient(credentials, config); + _client = sqsClient; _queuesPrefix = queuesPrefix; } diff --git a/test/WorkflowCore.Tests.DynamoDB/DynamoPersistenceProviderFixture.cs b/test/WorkflowCore.Tests.DynamoDB/DynamoPersistenceProviderFixture.cs index 6ec1c13b6..7d215f4ee 100644 --- a/test/WorkflowCore.Tests.DynamoDB/DynamoPersistenceProviderFixture.cs +++ b/test/WorkflowCore.Tests.DynamoDB/DynamoPersistenceProviderFixture.cs @@ -26,8 +26,9 @@ protected override IPersistenceProvider Subject if (_subject == null) { var cfg = new AmazonDynamoDBConfig { ServiceURL = DynamoDbDockerSetup.ConnectionString }; - var provisioner = new DynamoDbProvisioner(DynamoDbDockerSetup.Credentials, cfg, null, "unittests", new LoggerFactory()); - var client = new DynamoPersistenceProvider(DynamoDbDockerSetup.Credentials, cfg, null, provisioner, "unittests", new LoggerFactory()); + var dbClient = new AmazonDynamoDBClient(DynamoDbDockerSetup.Credentials, cfg); + var provisioner = new DynamoDbProvisioner(dbClient, "unittests", new LoggerFactory()); + var client = new DynamoPersistenceProvider(dbClient, provisioner, "unittests", new LoggerFactory()); client.EnsureStoreExists(); _subject = client; } From e1829f8174d78c03852ac16281b9b1c084ef7347 Mon Sep 17 00:00:00 2001 From: Stuart McKenzie Date: Fri, 28 Apr 2023 11:40:23 +1000 Subject: [PATCH 260/342] better patterns in the Service Collection Extensions (use the extension methods as intended) --- .../ServiceCollectionExtensions.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs index 5d62bf3dc..c3c545f80 100644 --- a/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.AWS/ServiceCollectionExtensions.cs @@ -17,7 +17,7 @@ public static class ServiceCollectionExtensions public static WorkflowOptions UseAwsSimpleQueueService(this WorkflowOptions options, AWSCredentials credentials, AmazonSQSConfig config, string queuesPrefix = "workflowcore") { var sqsClient = new AmazonSQSClient(credentials, config); - return UseAwsSimpleQueueServiceWithProvisionedClient(options, sqsClient, queuesPrefix); + return options.UseAwsSimpleQueueServiceWithProvisionedClient(sqsClient, queuesPrefix); } public static WorkflowOptions UseAwsSimpleQueueServiceWithProvisionedClient(this WorkflowOptions options, AmazonSQSClient sqsClient, string queuesPrefix = "workflowcore") @@ -29,7 +29,7 @@ public static WorkflowOptions UseAwsSimpleQueueServiceWithProvisionedClient(this public static WorkflowOptions UseAwsDynamoLocking(this WorkflowOptions options, AWSCredentials credentials, AmazonDynamoDBConfig config, string tableName) { var dbClient = new AmazonDynamoDBClient(credentials, config); - return UseAwsDynamoLockingWithProvisionedClient(options, dbClient, tableName); + return options.UseAwsDynamoLockingWithProvisionedClient(dbClient, tableName); } public static WorkflowOptions UseAwsDynamoLockingWithProvisionedClient (this WorkflowOptions options, AmazonDynamoDBClient dynamoClient, string tableName) @@ -41,7 +41,7 @@ public static WorkflowOptions UseAwsDynamoLockingWithProvisionedClient (this Wor public static WorkflowOptions UseAwsDynamoPersistence(this WorkflowOptions options, AWSCredentials credentials, AmazonDynamoDBConfig config, string tablePrefix) { var dbClient = new AmazonDynamoDBClient(credentials, config); - return UseAwsDynamoPersistenceWithProvisionedClient(options, dbClient, tablePrefix); + return options.UseAwsDynamoPersistenceWithProvisionedClient(dbClient, tablePrefix); } public static WorkflowOptions UseAwsDynamoPersistenceWithProvisionedClient(this WorkflowOptions options, AmazonDynamoDBClient dynamoClient, string tablePrefix) @@ -56,7 +56,7 @@ public static WorkflowOptions UseAwsKinesis(this WorkflowOptions options, AWSCre var kinesisClient = new AmazonKinesisClient(credentials, region); var dynamoClient = new AmazonDynamoDBClient(credentials, region); - return UseAwsKinesisWithProvisionedClients(options, kinesisClient, dynamoClient,appName, streamName); + return options.UseAwsKinesisWithProvisionedClients(kinesisClient, dynamoClient,appName, streamName); } From fcbb47aa84aa9eb79cae108d27a04bfc2f20c311 Mon Sep 17 00:00:00 2001 From: muelr Date: Thu, 4 May 2023 16:47:58 +0200 Subject: [PATCH 261/342] added a type resolver to be replaced by another implementation later. --- src/WorkflowCore.DSL/Interface/ITypeResolver.cs | 10 ++++++++++ .../ServiceCollectionExtensions.cs | 1 + src/WorkflowCore.DSL/Services/DefinitionLoader.cs | 15 +++++++++------ src/WorkflowCore.DSL/Services/TypeResolver.cs | 15 +++++++++++++++ .../DefinitionStorage/DefinitionLoaderTests.cs | 2 +- 5 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 src/WorkflowCore.DSL/Interface/ITypeResolver.cs create mode 100644 src/WorkflowCore.DSL/Services/TypeResolver.cs diff --git a/src/WorkflowCore.DSL/Interface/ITypeResolver.cs b/src/WorkflowCore.DSL/Interface/ITypeResolver.cs new file mode 100644 index 000000000..e9e54e49b --- /dev/null +++ b/src/WorkflowCore.DSL/Interface/ITypeResolver.cs @@ -0,0 +1,10 @@ +using System; +using System.Linq; + +namespace WorkflowCore.Interface +{ + public interface ITypeResolver + { + Type FindType(string name); + } +} \ No newline at end of file diff --git a/src/WorkflowCore.DSL/ServiceCollectionExtensions.cs b/src/WorkflowCore.DSL/ServiceCollectionExtensions.cs index 5c4944f4f..a4958e6b4 100644 --- a/src/WorkflowCore.DSL/ServiceCollectionExtensions.cs +++ b/src/WorkflowCore.DSL/ServiceCollectionExtensions.cs @@ -9,6 +9,7 @@ public static class ServiceCollectionExtensions { public static IServiceCollection AddWorkflowDSL(this IServiceCollection services) { + services.AddTransient(); services.AddTransient(); return services; } diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index ef7fadc9a..c5cc5e083 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -17,10 +17,12 @@ namespace WorkflowCore.Services.DefinitionStorage public class DefinitionLoader : IDefinitionLoader { private readonly IWorkflowRegistry _registry; + private readonly ITypeResolver _typeResolver; - public DefinitionLoader(IWorkflowRegistry registry) + public DefinitionLoader(IWorkflowRegistry registry, ITypeResolver typeResolver) { _registry = registry; + _typeResolver = typeResolver; } public WorkflowDefinition LoadDefinition(string source, Func deserializer) @@ -220,10 +222,11 @@ private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, Wo var dataParameter = Expression.Parameter(dataType, "data"); - if(output.Key.Contains(".") || output.Key.Contains("[")) + if (output.Key.Contains(".") || output.Key.Contains("[")) { AttachNestedOutput(output, step, source, sourceExpr, dataParameter); - }else + } + else { AttachDirectlyOutput(output, step, dataType, sourceExpr, dataParameter); } @@ -259,11 +262,11 @@ private void AttachDirectlyOutput(KeyValuePair output, WorkflowS } - private void AttachNestedOutput( KeyValuePair output, WorkflowStep step, StepSourceV1 source, LambdaExpression sourceExpr, ParameterExpression dataParameter) + private void AttachNestedOutput(KeyValuePair output, WorkflowStep step, StepSourceV1 source, LambdaExpression sourceExpr, ParameterExpression dataParameter) { PropertyInfo propertyInfo = null; String[] paths = output.Key.Split('.'); - + Expression targetProperty = dataParameter; bool hasAddOutput = false; @@ -352,7 +355,7 @@ private void AttachOutcomes(StepSourceV1 source, Type dataType, WorkflowStep ste private Type FindType(string name) { - return Type.GetType(name, true, true); + return _typeResolver.FindType(name); } private static Action BuildScalarInputAction(KeyValuePair input, ParameterExpression dataParameter, ParameterExpression contextParameter, ParameterExpression environmentVarsParameter, PropertyInfo stepProperty) diff --git a/src/WorkflowCore.DSL/Services/TypeResolver.cs b/src/WorkflowCore.DSL/Services/TypeResolver.cs new file mode 100644 index 000000000..992d38948 --- /dev/null +++ b/src/WorkflowCore.DSL/Services/TypeResolver.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; +using WorkflowCore.Interface; + +namespace WorkflowCore.Services.DefinitionStorage +{ + public class TypeResolver : ITypeResolver + { + public Type FindType(string name) + { + return Type.GetType(name, true, true); + } + } +} diff --git a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs index 01a743e8a..c47ba054b 100644 --- a/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs +++ b/test/WorkflowCore.UnitTests/Services/DefinitionStorage/DefinitionLoaderTests.cs @@ -19,7 +19,7 @@ public class DefinitionLoaderTests public DefinitionLoaderTests() { _registry = A.Fake(); - _subject = new DefinitionLoader(_registry); + _subject = new DefinitionLoader(_registry, new TypeResolver()); } [Fact(DisplayName = "Should register workflow")] From b7de0a1bff9668f14bdb629b3c39a82da79cb7f5 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 9 May 2023 08:25:04 -0700 Subject: [PATCH 262/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index a617157cb..19614367d 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.8.2 - 3.8.2.0 - 3.8.2.0 + 3.8.3 + 3.8.3.0 + 3.8.3.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.8.2 + 3.8.3 From a423a7e72291e7ed257e2f25ec5dc2b48877ba08 Mon Sep 17 00:00:00 2001 From: Ben Edwards Date: Wed, 17 May 2023 12:42:16 +1000 Subject: [PATCH 263/342] Update EFCore to 7 Change all .net 6 package references to entity framework to 7.*. All tests pass :D --- .../WorkflowCore.Persistence.EntityFramework.csproj | 2 +- .../WorkflowCore.Persistence.MySQL.csproj | 4 ++-- .../WorkflowCore.Persistence.PostgreSQL.csproj | 8 ++++---- .../WorkflowCore.Persistence.SqlServer.csproj | 6 +++--- .../WorkflowCore.Persistence.Sqlite.csproj | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index 6ab835915..b5fb079c9 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index aaf1f79b0..8b87ba216 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -35,11 +35,11 @@ - + all runtime; build; native; contentfiles; analyzers - + diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index e321a340a..583c706f0 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -23,12 +23,12 @@ - - - + + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index be099421a..b6db766bd 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -24,11 +24,11 @@ - - + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj index 0bd622bde..88b9ceec9 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj +++ b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj @@ -24,7 +24,7 @@ - + From f63e7db6e2022c8115ecdd86195d458bae72ff85 Mon Sep 17 00:00:00 2001 From: Christian Jundt Date: Fri, 2 Jun 2023 21:01:24 +0200 Subject: [PATCH 264/342] La colonne ExternalToken est trop petite --- .../Migrations/20230310125506_InitialDatabase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs index 9766e7c40..cab8aee7c 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs @@ -72,7 +72,7 @@ protected override void Up(MigrationBuilder migrationBuilder) EventKey = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), SubscribeAsOf = table.Column(type: "TIMESTAMP(7)", nullable: false), SubscriptionData = table.Column(type: "NVARCHAR2(2000)", nullable: true), - ExternalToken = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), + ExternalToken = table.Column(type: "NVARCHAR2(400)", maxLength: 400, nullable: true), ExternalWorkerId = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), ExternalTokenExpiry = table.Column(type: "TIMESTAMP(7)", nullable: true) }, From c6f192de9a934dce65a803c1f39b8b11ddcb5bf4 Mon Sep 17 00:00:00 2001 From: Christian Jundt Date: Thu, 8 Jun 2023 11:25:37 +0200 Subject: [PATCH 265/342] Workflow.Data converti en CLOB --- .../Migrations/20230310125506_InitialDatabase.cs | 2 +- .../Migrations/OracleContextModelSnapshot.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs index cab8aee7c..e758e161d 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/20230310125506_InitialDatabase.cs @@ -93,7 +93,7 @@ protected override void Up(MigrationBuilder migrationBuilder) Description = table.Column(type: "NVARCHAR2(500)", maxLength: 500, nullable: true), Reference = table.Column(type: "NVARCHAR2(200)", maxLength: 200, nullable: true), NextExecution = table.Column(type: "NUMBER(19)", nullable: true), - Data = table.Column(type: "NVARCHAR2(2000)", nullable: true), + Data = table.Column(type: "CLOB", nullable: true), CreateTime = table.Column(type: "TIMESTAMP(7)", nullable: false), CompleteTime = table.Column(type: "TIMESTAMP(7)", nullable: true), Status = table.Column(type: "NUMBER(10)", nullable: false) diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs index 63a882eef..6d600dcc5 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs @@ -301,7 +301,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("TIMESTAMP(7)"); b.Property("Data") - .HasColumnType("NVARCHAR2(2000)"); + .HasColumnType("CLOB"); b.Property("Description") .HasMaxLength(500) From 12be88701780e1f1b2d5b5b5d98e7ce4df3e9913 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 13 Jun 2023 07:32:25 -0700 Subject: [PATCH 266/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 19614367d..5d86bd3a5 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.8.3 - 3.8.3.0 - 3.8.3.0 + 3.9.0 + 3.9.0.0 + 3.9.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.8.3 + 3.9.0 From 11d461c6bd1f87fd820f22078a7f756414b637dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Jun 2023 23:11:13 +0000 Subject: [PATCH 267/342] Bump System.Linq.Dynamic.Core in /src/WorkflowCore.DSL Bumps [System.Linq.Dynamic.Core](https://github.com/zzzprojects/System.Linq.Dynamic.Core) from 1.2.13 to 1.3.0. - [Release notes](https://github.com/zzzprojects/System.Linq.Dynamic.Core/releases) - [Changelog](https://github.com/zzzprojects/System.Linq.Dynamic.Core/blob/master/CHANGELOG.md) - [Commits](https://github.com/zzzprojects/System.Linq.Dynamic.Core/compare/v1.2.13...v1.3.0) --- updated-dependencies: - dependency-name: System.Linq.Dynamic.Core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- src/WorkflowCore.DSL/WorkflowCore.DSL.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj b/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj index b3ce61cef..94765a53e 100644 --- a/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj +++ b/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 @@ -11,7 +11,7 @@ - + From 1101bc2cb012b1ff6d867b0cc946285bb69dd18b Mon Sep 17 00:00:00 2001 From: sepehr Date: Sun, 30 Jul 2023 16:20:43 +0330 Subject: [PATCH 268/342] Fix Error Endpoint Routing does not support UseMvc --- src/samples/WebApiSample/WebApiSample/Startup.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/samples/WebApiSample/WebApiSample/Startup.cs b/src/samples/WebApiSample/WebApiSample/Startup.cs index 13a19ddd8..0eee8a49e 100644 --- a/src/samples/WebApiSample/WebApiSample/Startup.cs +++ b/src/samples/WebApiSample/WebApiSample/Startup.cs @@ -44,11 +44,14 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseDeveloperExceptionPage(); } - + app.UseRouting(); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1")); - app.UseMvc(); + app.UseEndpoints(endpoints => + { + endpoints.MapControllerRoute("default", "{controller=Workflows}/{action=Get}"); + }); var host = app.ApplicationServices.GetService(); host.RegisterWorkflow(); From 23553226b846e71524ddadcb63963c815ae52fea Mon Sep 17 00:00:00 2001 From: James White Date: Sun, 6 Aug 2023 14:45:58 -0700 Subject: [PATCH 269/342] Fixed usage of WorkflowStep.Name when it could be null in WorkflowActivity. --- src/Directory.Build.props | 8 ++++---- src/WorkflowCore/Services/WorkflowActivity.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 5d86bd3a5..b86b7e833 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.9.0 - 3.9.0.0 - 3.9.0.0 + 3.9.1 + 3.9.1.0 + 3.9.1.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.9.0 + 3.9.1 diff --git a/src/WorkflowCore/Services/WorkflowActivity.cs b/src/WorkflowCore/Services/WorkflowActivity.cs index b580f98b6..b4599d367 100644 --- a/src/WorkflowCore/Services/WorkflowActivity.cs +++ b/src/WorkflowCore/Services/WorkflowActivity.cs @@ -59,7 +59,7 @@ internal static void Enrich(WorkflowStep workflowStep) activity.DisplayName += $" step {stepName}"; activity.SetTag("workflow.step.id", workflowStep.Id); - activity.SetTag("workflow.step.name", workflowStep.Name); + activity.SetTag("workflow.step.name", stepName); activity.SetTag("workflow.step.type", workflowStep.BodyType.Name); } } From fb17943461bc5049ef33373c7b4479b8cbdcb08a Mon Sep 17 00:00:00 2001 From: Oleksii Korniienko Date: Sat, 25 Nov 2023 01:12:00 +0200 Subject: [PATCH 270/342] Upgrade to net8 and EF8 --- ...rkflowCore.Persistence.EntityFramework.csproj | 8 ++++++-- .../WorkflowCore.Persistence.MySQL.csproj | 8 ++++++++ .../WorkflowCore.Persistence.PostgreSQL.csproj | 16 ++++++++++++++-- .../WorkflowCore.Persistence.SqlServer.csproj | 13 ++++++++++++- .../WorkflowCore.Persistence.Sqlite.csproj | 6 +++++- test/Directory.Build.props | 4 ++-- 6 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index b5fb079c9..f161d1299 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -3,14 +3,14 @@ Workflow Core EntityFramework Core Persistence Provider Daniel Gerlag - netstandard2.1;net6.0 + netstandard2.1;net6.0;net8.0 WorkflowCore.Persistence.EntityFramework WorkflowCore.Persistence.EntityFramework workflow;.NET;Core;state machine;WorkflowCore;EntityFramework;EntityFrameworkCore https://github.com/danielgerlag/workflow-core https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git - https://github.com/danielgerlag/workflow-core.git + https://github.com/danielgerlag/workflow-core.git false false false @@ -25,6 +25,10 @@ + + + + diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index 8b87ba216..8fc2815dd 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -42,6 +42,14 @@ + + + all + runtime; build; native; contentfiles; analyzers + + + + diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index 583c706f0..c49965ef2 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -3,7 +3,7 @@ Workflow Core PostgreSQL Persistence Provider Daniel Gerlag - netstandard2.1;net6.0 + netstandard2.1;net6.0;net8.0 WorkflowCore.Persistence.PostgreSQL WorkflowCore.Persistence.PostgreSQL workflow;.NET;Core;state machine;WorkflowCore;PostgreSQL @@ -23,7 +23,7 @@ - + All @@ -34,6 +34,18 @@ + + + + + All + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index b6db766bd..cfef6609f 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -4,7 +4,7 @@ Workflow Core SQL Server Persistence Provider 1.8.0 Daniel Gerlag - netstandard2.1;net6.0 + netstandard2.1;net6.0;net8.0 WorkflowCore.Persistence.SqlServer WorkflowCore.Persistence.SqlServer workflow;.NET;Core;state machine;WorkflowCore @@ -34,6 +34,17 @@ + + + + All + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj index 88b9ceec9..1797e054b 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj +++ b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj @@ -4,7 +4,7 @@ Workflow Core Sqlite Persistence Provider 1.5.0 Daniel Gerlag - netstandard2.1;net6.0 + netstandard2.1;net6.0;net8.0 WorkflowCore.Persistence.Sqlite WorkflowCore.Persistence.Sqlite workflow;.NET;Core;state machine;WorkflowCore;Sqlite @@ -27,6 +27,10 @@ + + + + diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 3b2ad7341..3b7c6be3b 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -1,6 +1,6 @@ - net6.0;netcoreapp3.1 + net6.0;netcoreapp3.1;net8.0 latest false @@ -18,7 +18,7 @@ - + \ No newline at end of file From 18a06a87fc2b0908e77e643379c29bb6fb0e877c Mon Sep 17 00:00:00 2001 From: Oleksii Korniienko Date: Sat, 25 Nov 2023 01:37:10 +0200 Subject: [PATCH 271/342] Remove net8 and ef8 from WorkflowCore.Persistence.MySQL --- .../WorkflowCore.Persistence.MySQL.csproj | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index 8fc2815dd..8b87ba216 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -42,14 +42,6 @@ - - - all - runtime; build; native; contentfiles; analyzers - - - - From 3950936951452b2a2c90b219949df63ec8448c71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jan 2024 20:20:24 +0000 Subject: [PATCH 272/342] Bump System.Data.SqlClient Bumps [System.Data.SqlClient](https://github.com/dotnet/corefx) from 4.8.5 to 4.8.6. - [Release notes](https://github.com/dotnet/corefx/releases) - [Commits](https://github.com/dotnet/corefx/commits) --- updated-dependencies: - dependency-name: System.Data.SqlClient dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .../WorkflowCore.QueueProviders.SqlServer.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj index c24b7d89e..26e52c308 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj @@ -22,7 +22,7 @@ - + From a23067b3de0ee8c55bbf3a9504873fbd3ce9f503 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 10 Apr 2024 10:01:04 -0700 Subject: [PATCH 273/342] test project target framework --- test/ScratchPad/ScratchPad.csproj | 1 + .../WorkflowCore.IntegrationTests.csproj | 1 + .../WorkflowCore.Tests.DynamoDB.csproj | 4 ++++ .../WorkflowCore.Tests.Elasticsearch.csproj | 4 ++++ .../WorkflowCore.Tests.MongoDB.csproj | 1 + test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj | 4 ++++ .../WorkflowCore.Tests.PostgreSQL.csproj | 1 + .../WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj | 4 ++++ test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj | 4 ++++ .../WorkflowCore.Tests.SqlServer.csproj | 4 ++++ .../WorkflowCore.Tests.Sqlite.csproj | 4 ++++ test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj | 1 + 12 files changed, 33 insertions(+) diff --git a/test/ScratchPad/ScratchPad.csproj b/test/ScratchPad/ScratchPad.csproj index a194035c2..4e58ba3b1 100644 --- a/test/ScratchPad/ScratchPad.csproj +++ b/test/ScratchPad/ScratchPad.csproj @@ -8,6 +8,7 @@ false false false + net6.0;net8.0 diff --git a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj index bdc973728..c92182936 100644 --- a/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj +++ b/test/WorkflowCore.IntegrationTests/WorkflowCore.IntegrationTests.csproj @@ -7,6 +7,7 @@ false false false + net6.0 diff --git a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj index 65320489d..6de478177 100644 --- a/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj +++ b/test/WorkflowCore.Tests.DynamoDB/WorkflowCore.Tests.DynamoDB.csproj @@ -1,5 +1,9 @@ + + net6.0 + + diff --git a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj index 9aa005f40..d5bae6c71 100644 --- a/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj +++ b/test/WorkflowCore.Tests.Elasticsearch/WorkflowCore.Tests.Elasticsearch.csproj @@ -1,5 +1,9 @@  + + net6.0 + + diff --git a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj index c708f7bf3..d30af9bec 100644 --- a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj +++ b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj @@ -7,6 +7,7 @@ false false false + net6.0 diff --git a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj index a56acc9b7..4ee96725f 100644 --- a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj +++ b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj @@ -1,5 +1,9 @@ + + net6.0 + + diff --git a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj index 66cc649b4..53a91aa9a 100644 --- a/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj +++ b/test/WorkflowCore.Tests.PostgreSQL/WorkflowCore.Tests.PostgreSQL.csproj @@ -7,6 +7,7 @@ false false false + net6.0;net8.0 diff --git a/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj b/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj index 98e658fed..5fc77518a 100644 --- a/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj +++ b/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj @@ -1,5 +1,9 @@ + + net6.0 + + diff --git a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj index 147dad6da..f6a8aaed1 100644 --- a/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj +++ b/test/WorkflowCore.Tests.Redis/WorkflowCore.Tests.Redis.csproj @@ -1,5 +1,9 @@ + + net6.0 + + diff --git a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj index 24e83536e..bf9557556 100644 --- a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj +++ b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj @@ -1,5 +1,9 @@  + + net6.0;net8.0 + + diff --git a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj index 63acee283..e3e981713 100644 --- a/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj +++ b/test/WorkflowCore.Tests.Sqlite/WorkflowCore.Tests.Sqlite.csproj @@ -1,5 +1,9 @@  + + net6.0;net8.0 + + diff --git a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj index 3ca6d6038..ff8f2e19e 100644 --- a/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj +++ b/test/WorkflowCore.UnitTests/WorkflowCore.UnitTests.csproj @@ -7,6 +7,7 @@ false false false + net6.0 From 14d563f2df0ded3d19fb55c9b330d8b26318b460 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 10 Apr 2024 12:27:18 -0700 Subject: [PATCH 274/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index b86b7e833..2a61e9808 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.9.1 - 3.9.1.0 - 3.9.1.0 + 3.10.0 + 3.10.0.0 + 3.10.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.9.1 + 3.10.0 From a761d783fe6f6bf9b0c6797321a439bf6f94c827 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 10 Apr 2024 17:01:55 -0700 Subject: [PATCH 275/342] vulnerable packages --- .../WorkflowCore.LockProviders.SqlServer.csproj | 2 +- .../WorkflowCore.QueueProviders.SqlServer.csproj | 2 +- src/samples/Directory.Build.props | 2 +- test/Directory.Build.props | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj b/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj index 5c798129a..f703c21ab 100644 --- a/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj index c24b7d89e..26e52c308 100644 --- a/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.QueueProviders.SqlServer/WorkflowCore.QueueProviders.SqlServer.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/samples/Directory.Build.props b/src/samples/Directory.Build.props index 0f8bd594d..8e4a35270 100644 --- a/src/samples/Directory.Build.props +++ b/src/samples/Directory.Build.props @@ -1,6 +1,6 @@ - net6.0;netcoreapp3.1 + net6.0 latest false diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 3b7c6be3b..2dc7c95f9 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -1,6 +1,6 @@ - net6.0;netcoreapp3.1;net8.0 + net6.0;net8.0 latest false From 9b9a5e2de529163de75da4a37082dc1480096f4e Mon Sep 17 00:00:00 2001 From: Veal Wang <49362109@qq.com> Date: Fri, 19 Apr 2024 09:31:20 +0800 Subject: [PATCH 276/342] Update correct workflow name for Sample09s --- src/samples/WorkflowCore.Sample09s/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/samples/WorkflowCore.Sample09s/Program.cs b/src/samples/WorkflowCore.Sample09s/Program.cs index 09e04abb8..2c60afe02 100644 --- a/src/samples/WorkflowCore.Sample09s/Program.cs +++ b/src/samples/WorkflowCore.Sample09s/Program.cs @@ -16,7 +16,7 @@ public static void Main(string[] args) host.Start(); Console.WriteLine("Starting workflow..."); - string workflowId = host.StartWorkflow("Foreach").Result; + string workflowId = host.StartWorkflow("ForeachSync").Result; Console.ReadLine(); @@ -41,4 +41,4 @@ private static IServiceProvider ConfigureServices() } } -} \ No newline at end of file +} From c1e45e0ae17a7f8b5c0fc24f59f215ba0f92d840 Mon Sep 17 00:00:00 2001 From: weibaohui Date: Fri, 26 Apr 2024 11:35:42 +0800 Subject: [PATCH 277/342] fix type error fix type error --- src/samples/WorkflowCore.Sample09s/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/samples/WorkflowCore.Sample09s/Program.cs b/src/samples/WorkflowCore.Sample09s/Program.cs index 09e04abb8..2c60afe02 100644 --- a/src/samples/WorkflowCore.Sample09s/Program.cs +++ b/src/samples/WorkflowCore.Sample09s/Program.cs @@ -16,7 +16,7 @@ public static void Main(string[] args) host.Start(); Console.WriteLine("Starting workflow..."); - string workflowId = host.StartWorkflow("Foreach").Result; + string workflowId = host.StartWorkflow("ForeachSync").Result; Console.ReadLine(); @@ -41,4 +41,4 @@ private static IServiceProvider ConfigureServices() } } -} \ No newline at end of file +} From 04c116cbec3916ce30695b338d57fb4484909980 Mon Sep 17 00:00:00 2001 From: Dani Horon Date: Thu, 9 May 2024 15:00:16 +0300 Subject: [PATCH 278/342] fix: prevent redis provider from crashing when using deleteComplete --- .../Services/RedisPersistenceProvider.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs index 6bf8df875..eb76fa29e 100644 --- a/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Providers.Redis/Services/RedisPersistenceProvider.cs @@ -92,6 +92,10 @@ public Task> GetWorkflowInstances(WorkflowStatus? public async Task GetWorkflowInstance(string Id, CancellationToken _ = default) { var raw = await _redis.HashGetAsync($"{_prefix}.{WORKFLOW_SET}", Id); + if (!raw.HasValue) + { + return null; + } return JsonConvert.DeserializeObject(raw, _serializerSettings); } From f72cc11b2e3ebc15ea3fbfbd4296d098ab8409cf Mon Sep 17 00:00:00 2001 From: "Xi Wang (AZURE)" Date: Fri, 24 May 2024 14:49:03 -0700 Subject: [PATCH 279/342] [Providers.Azure] Move away from deprecated libs and support TokenCredential --- .../Models/ControlledLock.cs | 7 +- .../ServiceCollectionExtensions.cs | 43 ++++++++++- .../Services/AzureLockManager.cs | 35 +++++---- .../Services/AzureStorageQueueProvider.cs | 41 ++++++----- .../Services/CosmosClientFactory.cs | 6 ++ .../Services/ServiceBusLifeCycleEventHub.cs | 73 +++++++++++-------- .../WorkflowCore.Providers.Azure.csproj | 8 +- 7 files changed, 142 insertions(+), 71 deletions(-) diff --git a/src/providers/WorkflowCore.Providers.Azure/Models/ControlledLock.cs b/src/providers/WorkflowCore.Providers.Azure/Models/ControlledLock.cs index 5b0343456..587378e15 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Models/ControlledLock.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Models/ControlledLock.cs @@ -1,5 +1,4 @@ -using System; -using Microsoft.WindowsAzure.Storage.Blob; +using Azure.Storage.Blobs.Specialized; namespace WorkflowCore.Providers.Azure.Models { @@ -7,9 +6,9 @@ class ControlledLock { public string Id { get; set; } public string LeaseId { get; set; } - public CloudBlockBlob Blob { get; set; } + public BlockBlobClient Blob { get; set; } - public ControlledLock(string id, string leaseId, CloudBlockBlob blob) + public ControlledLock(string id, string leaseId, BlockBlobClient blob) { Id = id; LeaseId = leaseId; diff --git a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs index 0aa1963e4..6e3a92d5d 100644 --- a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs @@ -1,4 +1,6 @@ -using Microsoft.Extensions.Logging; +using System; +using Azure.Core; +using Microsoft.Extensions.Logging; using WorkflowCore.Interface; using WorkflowCore.Models; using WorkflowCore.Providers.Azure.Interface; @@ -15,6 +17,13 @@ public static WorkflowOptions UseAzureSynchronization(this WorkflowOptions optio return options; } + public static WorkflowOptions UseAzureSynchronization(this WorkflowOptions options, Uri blobEndpoint, Uri queueEndpoint, TokenCredential tokenCredential) + { + options.UseQueueProvider(sp => new AzureStorageQueueProvider(queueEndpoint, tokenCredential, sp.GetService())); + options.UseDistributedLockManager(sp => new AzureLockManager(blobEndpoint, tokenCredential, sp.GetService())); + return options; + } + public static WorkflowOptions UseAzureServiceBusEventHub( this WorkflowOptions options, string connectionString, @@ -27,6 +36,19 @@ public static WorkflowOptions UseAzureServiceBusEventHub( return options; } + public static WorkflowOptions UseAzureServiceBusEventHub( + this WorkflowOptions options, + string fullyQualifiedNamespace, + TokenCredential tokenCredential, + string topicName, + string subscriptionName) + { + options.UseEventHub(sp => new ServiceBusLifeCycleEventHub( + fullyQualifiedNamespace, tokenCredential, topicName, subscriptionName, sp.GetService())); + + return options; + } + public static WorkflowOptions UseCosmosDbPersistence( this WorkflowOptions options, string connectionString, @@ -44,5 +66,24 @@ public static WorkflowOptions UseCosmosDbPersistence( options.UsePersistence(sp => new CosmosDbPersistenceProvider(sp.GetService(), databaseId, sp.GetService(), cosmosDbStorageOptions)); return options; } + + public static WorkflowOptions UseCosmosDbPersistence( + this WorkflowOptions options, + string accountEndpoint, + TokenCredential tokenCredential, + string databaseId, + CosmosDbStorageOptions cosmosDbStorageOptions = null) + { + if (cosmosDbStorageOptions == null) + { + cosmosDbStorageOptions = new CosmosDbStorageOptions(); + } + + options.Services.AddSingleton(sp => new CosmosClientFactory(accountEndpoint, tokenCredential)); + options.Services.AddTransient(sp => new CosmosDbProvisioner(sp.GetService(), cosmosDbStorageOptions)); + options.Services.AddSingleton(sp => new WorkflowPurger(sp.GetService(), databaseId, cosmosDbStorageOptions)); + options.UsePersistence(sp => new CosmosDbPersistenceProvider(sp.GetService(), databaseId, sp.GetService(), cosmosDbStorageOptions)); + return options; + } } } diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs b/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs index c52e823c7..d0134f790 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Azure.Core; +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Specialized; using Microsoft.Extensions.Logging; -using Microsoft.WindowsAzure.Storage; -using Microsoft.WindowsAzure.Storage.Blob; using WorkflowCore.Interface; using WorkflowCore.Providers.Azure.Models; @@ -13,11 +15,11 @@ namespace WorkflowCore.Providers.Azure.Services { public class AzureLockManager: IDistributedLockProvider { - private readonly CloudBlobClient _client; + private readonly BlobServiceClient _client; private readonly ILogger _logger; private readonly List _locks = new List(); private readonly AutoResetEvent _mutex = new AutoResetEvent(true); - private CloudBlobContainer _container; + private BlobContainerClient _container; private Timer _renewTimer; private TimeSpan LockTimeout => TimeSpan.FromMinutes(1); private TimeSpan RenewInterval => TimeSpan.FromSeconds(45); @@ -25,26 +27,31 @@ public class AzureLockManager: IDistributedLockProvider public AzureLockManager(string connectionString, ILoggerFactory logFactory) { _logger = logFactory.CreateLogger(); - var account = CloudStorageAccount.Parse(connectionString); - _client = account.CreateCloudBlobClient(); + _client = new BlobServiceClient(connectionString); + } + + public AzureLockManager(Uri blobEndpoint, TokenCredential tokenCredential, ILoggerFactory logFactory) + { + _logger = logFactory.CreateLogger(); + _client = new BlobServiceClient(blobEndpoint, tokenCredential); } public async Task AcquireLock(string Id, CancellationToken cancellationToken) { - var blob = _container.GetBlockBlobReference(Id); + var blob = _container.GetBlockBlobClient(Id); if (!await blob.ExistsAsync()) - await blob.UploadTextAsync(string.Empty); + await blob.UploadAsync(new MemoryStream()); if (_mutex.WaitOne()) { try { - var leaseId = await blob.AcquireLeaseAsync(LockTimeout); - _locks.Add(new ControlledLock(Id, leaseId, blob)); + var lease = await blob.GetBlobLeaseClient().AcquireAsync(LockTimeout); + _locks.Add(new ControlledLock(Id, lease.Value.LeaseId, blob)); return true; } - catch (StorageException ex) + catch (Exception ex) { _logger.LogDebug($"Failed to acquire lock {Id} - {ex.Message}"); return false; @@ -69,7 +76,7 @@ public async Task ReleaseLock(string Id) { try { - await entry.Blob.ReleaseLeaseAsync(AccessCondition.GenerateLeaseCondition(entry.LeaseId)); + await entry.Blob.GetBlobLeaseClient(entry.LeaseId).ReleaseAsync(); } catch (Exception ex) { @@ -87,7 +94,7 @@ public async Task ReleaseLock(string Id) public async Task Start() { - _container = _client.GetContainerReference("workflowcore-locks"); + _container = _client.GetBlobContainerClient("workflowcore-locks"); await _container.CreateIfNotExistsAsync(); _renewTimer = new Timer(RenewLeases, null, RenewInterval, RenewInterval); } @@ -128,7 +135,7 @@ private async Task RenewLock(ControlledLock entry) { try { - await entry.Blob.RenewLeaseAsync(AccessCondition.GenerateLeaseCondition(entry.LeaseId)); + await entry.Blob.GetBlobLeaseClient(entry.LeaseId).ReleaseAsync(); } catch (Exception ex) { diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/AzureStorageQueueProvider.cs b/src/providers/WorkflowCore.Providers.Azure/Services/AzureStorageQueueProvider.cs index cbd76d1f7..3aea1d397 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/AzureStorageQueueProvider.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/AzureStorageQueueProvider.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Azure.Core; +using Azure.Storage.Queues; using Microsoft.Extensions.Logging; -using Microsoft.WindowsAzure.Storage; -using Microsoft.WindowsAzure.Storage.Queue; using WorkflowCore.Interface; namespace WorkflowCore.Providers.Azure.Services @@ -13,41 +13,44 @@ public class AzureStorageQueueProvider : IQueueProvider { private readonly ILogger _logger; - private readonly Dictionary _queues = new Dictionary(); + private readonly Dictionary _queues = new Dictionary(); public bool IsDequeueBlocking => false; public AzureStorageQueueProvider(string connectionString, ILoggerFactory logFactory) { _logger = logFactory.CreateLogger(); - var account = CloudStorageAccount.Parse(connectionString); - var client = account.CreateCloudQueueClient(); + var client = new QueueServiceClient(connectionString); - _queues[QueueType.Workflow] = client.GetQueueReference("workflowcore-workflows"); - _queues[QueueType.Event] = client.GetQueueReference("workflowcore-events"); - _queues[QueueType.Index] = client.GetQueueReference("workflowcore-index"); + _queues[QueueType.Workflow] = client.GetQueueClient("workflowcore-workflows"); + _queues[QueueType.Event] = client.GetQueueClient("workflowcore-events"); + _queues[QueueType.Index] = client.GetQueueClient("workflowcore-index"); + } + + public AzureStorageQueueProvider(Uri queueEndpoint, TokenCredential tokenCredential, ILoggerFactory logFactory) + { + _logger = logFactory.CreateLogger(); + var client = new QueueServiceClient(queueEndpoint, tokenCredential); + + _queues[QueueType.Workflow] = client.GetQueueClient("workflowcore-workflows"); + _queues[QueueType.Event] = client.GetQueueClient("workflowcore-events"); + _queues[QueueType.Index] = client.GetQueueClient("workflowcore-index"); } public async Task QueueWork(string id, QueueType queue) { - var msg = new CloudQueueMessage(id); - await _queues[queue].AddMessageAsync(msg); + await _queues[queue].SendMessageAsync(id); } public async Task DequeueWork(QueueType queue, CancellationToken cancellationToken) { - CloudQueue cloudQueue = _queues[queue]; - - if (cloudQueue == null) - return null; - - var msg = await cloudQueue.GetMessageAsync(); + var msg = await _queues[queue].ReceiveMessageAsync(); - if (msg == null) + if (msg == null || msg.Value == null) return null; - await cloudQueue.DeleteMessageAsync(msg); - return msg.AsString; + await _queues[queue].DeleteMessageAsync(msg.Value.MessageId, msg.Value.PopReceipt); + return msg.Value.Body.ToString(); } public async Task Start() diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs index 9cb4cc572..12b9d9b96 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs @@ -1,4 +1,5 @@ using System; +using Azure.Core; using Microsoft.Azure.Cosmos; using WorkflowCore.Providers.Azure.Interface; @@ -15,6 +16,11 @@ public CosmosClientFactory(string connectionString) _client = new CosmosClient(connectionString); } + public CosmosClientFactory(string accountEndpoint, TokenCredential tokenCredential) + { + _client = new CosmosClient(accountEndpoint, tokenCredential); + } + public CosmosClient GetCosmosClient() { return this._client; diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/ServiceBusLifeCycleEventHub.cs b/src/providers/WorkflowCore.Providers.Azure/Services/ServiceBusLifeCycleEventHub.cs index 85f7a4245..f1ce10984 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/ServiceBusLifeCycleEventHub.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/ServiceBusLifeCycleEventHub.cs @@ -3,7 +3,8 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using Microsoft.Azure.ServiceBus; +using Azure.Core; +using Azure.Messaging.ServiceBus; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using WorkflowCore.Interface; @@ -13,9 +14,11 @@ namespace WorkflowCore.Providers.Azure.Services { public class ServiceBusLifeCycleEventHub : ILifeCycleEventHub { - private readonly ITopicClient _topicClient; private readonly ILogger _logger; - private readonly ISubscriptionClient _subscriptionClient; + private readonly ServiceBusSender _sender; + private readonly ServiceBusReceiver _receiver; + private readonly ServiceBusProcessor _processor; + private readonly ICollection> _subscribers = new HashSet>(); private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings { @@ -29,20 +32,38 @@ public ServiceBusLifeCycleEventHub( string subscriptionName, ILoggerFactory logFactory) { - _subscriptionClient = new SubscriptionClient(connectionString, topicName, subscriptionName); - _topicClient = new TopicClient(connectionString, topicName); + var client = new ServiceBusClient(connectionString); + _sender = client.CreateSender(topicName); + _receiver = client.CreateReceiver(topicName, subscriptionName); + _processor = client.CreateProcessor(topicName, subscriptionName, new ServiceBusProcessorOptions + { + AutoCompleteMessages = false + }); _logger = logFactory.CreateLogger(GetType()); } - public async Task PublishNotification(LifeCycleEvent evt) + public ServiceBusLifeCycleEventHub( + string fullyQualifiedNamespace, + TokenCredential tokenCredential, + string topicName, + string subscriptionName, + ILoggerFactory logFactory) { - var payload = JsonConvert.SerializeObject(evt, _serializerSettings); - var message = new Message(Encoding.Default.GetBytes(payload)) + var client = new ServiceBusClient(fullyQualifiedNamespace, tokenCredential); + _sender = client.CreateSender(topicName); + _receiver = client.CreateReceiver(topicName, subscriptionName); + _processor = client.CreateProcessor(topicName, subscriptionName, new ServiceBusProcessorOptions { - Label = evt.Reference - }; + AutoCompleteMessages = false + }); + _logger = logFactory.CreateLogger(GetType()); + } - await _topicClient.SendAsync(message); + public async Task PublishNotification(LifeCycleEvent evt) + { + var payload = JsonConvert.SerializeObject(evt, _serializerSettings); + var message = new ServiceBusMessage(payload); + await _sender.SendMessageAsync(message); } public void Subscribe(Action action) @@ -50,45 +71,39 @@ public void Subscribe(Action action) _subscribers.Add(action); } - public Task Start() + public async Task Start() { - var messageHandlerOptions = new MessageHandlerOptions(ExceptionHandler) - { - AutoComplete = false - }; - - _subscriptionClient.RegisterMessageHandler(MessageHandler, messageHandlerOptions); - - return Task.CompletedTask; + _processor.ProcessErrorAsync += ExceptionHandler; + _processor.ProcessMessageAsync += MessageHandler; + await _processor.StartProcessingAsync(); } public async Task Stop() { - await _topicClient.CloseAsync(); - await _subscriptionClient.CloseAsync(); + await _sender.CloseAsync(); + await _receiver.CloseAsync(); + await _processor.CloseAsync(); } - private async Task MessageHandler(Message message, CancellationToken cancellationToken) + private async Task MessageHandler(ProcessMessageEventArgs args) { try { - var payload = Encoding.Default.GetString(message.Body); + var payload = args.Message.Body.ToString(); var evt = JsonConvert.DeserializeObject( payload, _serializerSettings); NotifySubscribers(evt); - await _subscriptionClient - .CompleteAsync(message.SystemProperties.LockToken) - .ConfigureAwait(false); + await _receiver.CompleteMessageAsync(args.Message); } catch { - await _subscriptionClient.AbandonAsync(message.SystemProperties.LockToken); + await _receiver.AbandonMessageAsync(args.Message); } } - private Task ExceptionHandler(ExceptionReceivedEventArgs arg) + private Task ExceptionHandler(ProcessErrorEventArgs arg) { _logger.LogWarning(default, arg.Exception, "Error on receiving events"); diff --git a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj index cedd72024..65517764c 100644 --- a/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj +++ b/src/providers/WorkflowCore.Providers.Azure/WorkflowCore.Providers.Azure.csproj @@ -16,10 +16,10 @@ - - - - + + + + From 4f75c7a2d246efff1bbfbf3d694d5fe7ccbaa4c0 Mon Sep 17 00:00:00 2001 From: Revazashvili Date: Sun, 26 May 2024 22:25:49 +0400 Subject: [PATCH 280/342] fix typo in PersistanceFactory --- src/WorkflowCore/Models/WorkflowOptions.cs | 6 +++--- src/WorkflowCore/ServiceCollectionExtensions.cs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/WorkflowCore/Models/WorkflowOptions.cs b/src/WorkflowCore/Models/WorkflowOptions.cs index 8913c32c2..a4432afff 100644 --- a/src/WorkflowCore/Models/WorkflowOptions.cs +++ b/src/WorkflowCore/Models/WorkflowOptions.cs @@ -8,7 +8,7 @@ namespace WorkflowCore.Models { public class WorkflowOptions { - internal Func PersistanceFactory; + internal Func PersistenceFactory; internal Func QueueFactory; internal Func LockFactory; internal Func EventHubFactory; @@ -29,7 +29,7 @@ public WorkflowOptions(IServiceCollection services) QueueFactory = new Func(sp => new SingleNodeQueueProvider()); LockFactory = new Func(sp => new SingleNodeLockProvider()); - PersistanceFactory = new Func(sp => new TransientMemoryPersistenceProvider(sp.GetService())); + PersistenceFactory = new Func(sp => new TransientMemoryPersistenceProvider(sp.GetService())); SearchIndexFactory = new Func(sp => new NullSearchIndex()); EventHubFactory = new Func(sp => new SingleNodeEventHub(sp.GetService())); } @@ -42,7 +42,7 @@ public WorkflowOptions(IServiceCollection services) public void UsePersistence(Func factory) { - PersistanceFactory = factory; + PersistenceFactory = factory; } public void UseDistributedLockManager(Func factory) diff --git a/src/WorkflowCore/ServiceCollectionExtensions.cs b/src/WorkflowCore/ServiceCollectionExtensions.cs index 760a89d41..f38f44a5b 100644 --- a/src/WorkflowCore/ServiceCollectionExtensions.cs +++ b/src/WorkflowCore/ServiceCollectionExtensions.cs @@ -20,10 +20,10 @@ public static IServiceCollection AddWorkflow(this IServiceCollection services, A var options = new WorkflowOptions(services); setupAction?.Invoke(options); services.AddSingleton(); - services.AddTransient(options.PersistanceFactory); - services.AddTransient(options.PersistanceFactory); - services.AddTransient(options.PersistanceFactory); - services.AddTransient(options.PersistanceFactory); + services.AddTransient(options.PersistenceFactory); + services.AddTransient(options.PersistenceFactory); + services.AddTransient(options.PersistenceFactory); + services.AddTransient(options.PersistenceFactory); services.AddSingleton(options.QueueFactory); services.AddSingleton(options.LockFactory); services.AddSingleton(options.EventHubFactory); From 2a0b27b5bf2d8b1b3b1813940f2d7a34135d45d8 Mon Sep 17 00:00:00 2001 From: "Xi Wang (AZURE)" Date: Thu, 30 May 2024 08:18:56 -0700 Subject: [PATCH 281/342] Fix typo --- .../WorkflowCore.Providers.Azure/Services/AzureLockManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs b/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs index d0134f790..6780a77ad 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/AzureLockManager.cs @@ -135,7 +135,7 @@ private async Task RenewLock(ControlledLock entry) { try { - await entry.Blob.GetBlobLeaseClient(entry.LeaseId).ReleaseAsync(); + await entry.Blob.GetBlobLeaseClient(entry.LeaseId).RenewAsync(); } catch (Exception ex) { From cb7a69244a46cc0f31cc0af09d826f74c7380693 Mon Sep 17 00:00:00 2001 From: Michal Krzych Date: Wed, 5 Jun 2024 14:46:34 +0100 Subject: [PATCH 282/342] #1270 Fixed list items deserialization duplication --- .../ExtensionMethods.cs | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs index b0b2b1d99..536ccc7be 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/ExtensionMethods.cs @@ -9,12 +9,16 @@ namespace WorkflowCore.Persistence.EntityFramework { internal static class ExtensionMethods { - private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; + private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.All, + ObjectCreationHandling = ObjectCreationHandling.Replace + }; internal static PersistedWorkflow ToPersistable(this WorkflowInstance instance, PersistedWorkflow persistable = null) { - if (persistable == null) - persistable = new PersistedWorkflow(); + if (persistable == null) + persistable = new PersistedWorkflow(); persistable.Data = JsonConvert.SerializeObject(instance.Data, SerializerSettings); persistable.Description = instance.Description; @@ -25,19 +29,19 @@ internal static PersistedWorkflow ToPersistable(this WorkflowInstance instance, persistable.WorkflowDefinitionId = instance.WorkflowDefinitionId; persistable.Status = instance.Status; persistable.CreateTime = instance.CreateTime; - persistable.CompleteTime = instance.CompleteTime; - + persistable.CompleteTime = instance.CompleteTime; + foreach (var ep in instance.ExecutionPointers) { var persistedEP = persistable.ExecutionPointers.FindById(ep.Id); - + if (persistedEP == null) { persistedEP = new PersistedExecutionPointer(); persistedEP.Id = ep.Id ?? Guid.NewGuid().ToString(); persistable.ExecutionPointers.Add(persistedEP); - } - + } + persistedEP.StepId = ep.StepId; persistedEP.Active = ep.Active; persistedEP.SleepUntil = ep.SleepUntil; @@ -83,7 +87,7 @@ internal static PersistedWorkflow ToPersistable(this WorkflowInstance instance, internal static PersistedExecutionError ToPersistable(this ExecutionError instance) { - var result = new PersistedExecutionError(); + var result = new PersistedExecutionError(); result.ErrorTime = instance.ErrorTime; result.Message = instance.Message; result.ExecutionPointerId = instance.ExecutionPointerId; @@ -94,7 +98,7 @@ internal static PersistedExecutionError ToPersistable(this ExecutionError instan internal static PersistedSubscription ToPersistable(this EventSubscription instance) { - PersistedSubscription result = new PersistedSubscription(); + PersistedSubscription result = new PersistedSubscription(); result.SubscriptionId = new Guid(instance.Id); result.EventKey = instance.EventKey; result.EventName = instance.EventName; @@ -106,7 +110,7 @@ internal static PersistedSubscription ToPersistable(this EventSubscription insta result.ExternalToken = instance.ExternalToken; result.ExternalTokenExpiry = instance.ExternalTokenExpiry; result.ExternalWorkerId = instance.ExternalWorkerId; - + return result; } @@ -152,7 +156,7 @@ internal static WorkflowInstance ToWorkflowInstance(this PersistedWorkflow insta foreach (var ep in instance.ExecutionPointers) { - var pointer = new ExecutionPointer(); + var pointer = new ExecutionPointer(); pointer.Id = ep.Id; pointer.StepId = ep.StepId; From e53090068529248ffc29e6359db8160d1d9e6ed5 Mon Sep 17 00:00:00 2001 From: James White Date: Wed, 31 Jul 2024 18:17:56 -0700 Subject: [PATCH 283/342] Fixed additional null refs in workflow activity enrichment methods --- src/WorkflowCore/Services/WorkflowActivity.cs | 39 ++++++++----------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/src/WorkflowCore/Services/WorkflowActivity.cs b/src/WorkflowCore/Services/WorkflowActivity.cs index b4599d367..9230f5956 100644 --- a/src/WorkflowCore/Services/WorkflowActivity.cs +++ b/src/WorkflowCore/Services/WorkflowActivity.cs @@ -35,19 +35,6 @@ internal static Activity StartPoll(string type) return activity; } - - internal static void Enrich(WorkflowInstance workflow, string action) - { - var activity = Activity.Current; - if (activity != null) - { - activity.DisplayName = $"workflow {action} {workflow.WorkflowDefinitionId}"; - activity.SetTag("workflow.id", workflow.Id); - activity.SetTag("workflow.definition", workflow.WorkflowDefinitionId); - activity.SetTag("workflow.status", workflow.Status); - } - } - internal static void Enrich(WorkflowStep workflowStep) { var activity = Activity.Current; @@ -57,10 +44,18 @@ internal static void Enrich(WorkflowStep workflowStep) ? "inline" : workflowStep.Name; - activity.DisplayName += $" step {stepName}"; + if (string.IsNullOrEmpty(activity.DisplayName)) + { + activity.DisplayName = $"step {stepName}"; + } + else + { + activity.DisplayName += $" step {stepName}"; + } + activity.SetTag("workflow.step.id", workflowStep.Id); activity.SetTag("workflow.step.name", stepName); - activity.SetTag("workflow.step.type", workflowStep.BodyType.Name); + activity.SetTag("workflow.step.type", workflowStep.BodyType?.Name); } } @@ -69,10 +64,10 @@ internal static void Enrich(WorkflowExecutorResult result) var activity = Activity.Current; if (activity != null) { - activity.SetTag("workflow.subscriptions.count", result.Subscriptions.Count); - activity.SetTag("workflow.errors.count", result.Errors.Count); + activity.SetTag("workflow.subscriptions.count", result?.Subscriptions?.Count); + activity.SetTag("workflow.errors.count", result?.Errors?.Count); - if (result.Errors.Count > 0) + if (result?.Errors?.Count > 0) { activity.SetStatus(Status.Error); activity.SetStatus(ActivityStatusCode.Error); @@ -85,10 +80,10 @@ internal static void Enrich(Event evt) var activity = Activity.Current; if (activity != null) { - activity.DisplayName = $"workflow process {evt.EventName}"; - activity.SetTag("workflow.event.id", evt.Id); - activity.SetTag("workflow.event.name", evt.EventName); - activity.SetTag("workflow.event.processed", evt.IsProcessed); + activity.DisplayName = $"workflow process {evt?.EventName}"; + activity.SetTag("workflow.event.id", evt?.Id); + activity.SetTag("workflow.event.name", evt?.EventName); + activity.SetTag("workflow.event.processed", evt?.IsProcessed); } } From bb7b4acaa069621f39d468a35387c2989d7aa332 Mon Sep 17 00:00:00 2001 From: James White Date: Wed, 31 Jul 2024 18:24:40 -0700 Subject: [PATCH 284/342] Update to include new WorkflowInstance method from master --- src/WorkflowCore/Services/WorkflowActivity.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/WorkflowCore/Services/WorkflowActivity.cs b/src/WorkflowCore/Services/WorkflowActivity.cs index 9230f5956..80c719fb8 100644 --- a/src/WorkflowCore/Services/WorkflowActivity.cs +++ b/src/WorkflowCore/Services/WorkflowActivity.cs @@ -35,6 +35,20 @@ internal static Activity StartPoll(string type) return activity; } + + internal static void Enrich(WorkflowInstance workflow, string action) + { + var activity = Activity.Current; + if (activity != null) + { + activity.DisplayName = $"workflow {action} {workflow.WorkflowDefinitionId}"; + activity.SetTag("workflow.id", workflow.Id); + activity.SetTag("workflow.definition", workflow.WorkflowDefinitionId); + activity.SetTag("workflow.status", workflow.Status); + } + } + + internal static void Enrich(WorkflowStep workflowStep) { var activity = Activity.Current; From 8f4e583ae3531c3254170e9f85c1aeebda4ed5a3 Mon Sep 17 00:00:00 2001 From: Thiago Vaz Dias <1681936+tvdias@users.noreply.github.com> Date: Sat, 3 Aug 2024 12:21:17 +0100 Subject: [PATCH 285/342] Fix typo on README.md --- src/providers/WorkflowCore.Providers.Redis/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Providers.Redis/README.md b/src/providers/WorkflowCore.Providers.Redis/README.md index 9edc8f31e..a8a610298 100644 --- a/src/providers/WorkflowCore.Providers.Redis/README.md +++ b/src/providers/WorkflowCore.Providers.Redis/README.md @@ -35,6 +35,6 @@ services.AddWorkflow(cfg => cfg.UseRedisPersistence("localhost:6379", "app-name"); cfg.UseRedisLocking("localhost:6379"); cfg.UseRedisQueues("localhost:6379", "app-name"); - cfg.UseRedisEventHub("localhost:6379", "channel-name") + cfg.UseRedisEventHub("localhost:6379", "channel-name"); }); ``` From a49684529bf65fa15ac9715d298cb1bd6abd45d1 Mon Sep 17 00:00:00 2001 From: Joaquim Tomas Date: Wed, 14 Aug 2024 10:43:51 +0100 Subject: [PATCH 286/342] bump: rabbitmq client version to 6.8.1 --- .../WorkflowCore.QueueProviders.RabbitMQ.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj index 3ef1064ae..df02daa76 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj @@ -23,7 +23,7 @@ - + From fd19caa4ac81bda6ee05fb5c28dbc5599eaad885 Mon Sep 17 00:00:00 2001 From: Joaquim Tomas Date: Wed, 14 Aug 2024 10:44:25 +0100 Subject: [PATCH 287/342] fix: readonlymemory byte to byte array --- .../Services/RabbitMQProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs index 64322ad50..8a4ab33bb 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs @@ -63,7 +63,7 @@ public async Task DequeueWork(QueueType queue, CancellationToken cancell var msg = channel.BasicGet(_queueNameProvider.GetQueueName(queue), false); if (msg != null) { - var data = Encoding.UTF8.GetString(msg.Body); + var data = Encoding.UTF8.GetString(msg.Body.ToArray()); channel.BasicAck(msg.DeliveryTag, false); return data; } From da17e9ee7ea13b99142eb2e0c867e27492e9c2ef Mon Sep 17 00:00:00 2001 From: Roland Schmitt Date: Wed, 14 Aug 2024 18:08:44 +0200 Subject: [PATCH 288/342] Fixed usage of CreateIndexes for mongo to avoid database connection already opening during ioc --- .../Services/MongoPersistenceProvider.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index fdab92cf6..d38ded2a5 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -23,7 +23,6 @@ public class MongoPersistenceProvider : IPersistenceProvider public MongoPersistenceProvider(IMongoDatabase database) { _database = database; - CreateIndexes(this); } static MongoPersistenceProvider() @@ -263,7 +262,7 @@ public async Task ClearSubscriptionToken(string eventSubscriptionId, string toke public void EnsureStoreExists() { - + CreateIndexes(this); } public async Task> GetSubscriptions(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) From 0b51d8ef84375354864da4d18a5b8c62ce2b7272 Mon Sep 17 00:00:00 2001 From: Roland Schmitt Date: Wed, 14 Aug 2024 18:35:44 +0200 Subject: [PATCH 289/342] Fixed mongo tests to call EnsureStoreExists --- .../MongoPersistenceProviderFixture.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/WorkflowCore.Tests.MongoDB/MongoPersistenceProviderFixture.cs b/test/WorkflowCore.Tests.MongoDB/MongoPersistenceProviderFixture.cs index c61b4b5e2..fd6546aca 100644 --- a/test/WorkflowCore.Tests.MongoDB/MongoPersistenceProviderFixture.cs +++ b/test/WorkflowCore.Tests.MongoDB/MongoPersistenceProviderFixture.cs @@ -1,5 +1,4 @@ using MongoDB.Driver; -using System; using WorkflowCore.Interface; using WorkflowCore.Persistence.MongoDB.Services; using WorkflowCore.UnitTests; @@ -23,7 +22,9 @@ protected override IPersistenceProvider Subject { var client = new MongoClient(MongoDockerSetup.ConnectionString); var db = client.GetDatabase(nameof(MongoPersistenceProviderFixture)); - return new MongoPersistenceProvider(db); + var provider = new MongoPersistenceProvider(db); + provider.EnsureStoreExists(); + return provider; } } } From e1ebc7673ab8097fabe525158a98724c05a4e37d Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 14 Aug 2024 13:09:10 -0700 Subject: [PATCH 290/342] Update dotnet.yml --- .github/workflows/dotnet.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 83afb451b..cabbec099 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -17,6 +17,7 @@ jobs: dotnet-version: | 3.1.x 6.0.x + 8.0.x - name: Restore dependencies run: dotnet restore - name: Build @@ -134,4 +135,4 @@ jobs: - name: Build run: dotnet build --no-restore - name: Elasticsearch Tests - run: dotnet test test/WorkflowCore.Tests.Elasticsearch --no-build --verbosity normal -p:ParallelizeTestCollections=false \ No newline at end of file + run: dotnet test test/WorkflowCore.Tests.Elasticsearch --no-build --verbosity normal -p:ParallelizeTestCollections=false From e0ee5f29d7957558503c36247bb9a6685083ed27 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 20:10:39 +0000 Subject: [PATCH 291/342] Bump Npgsql in /src/providers/WorkflowCore.Persistence.PostgreSQL Bumps [Npgsql](https://github.com/npgsql/npgsql) from 5.0.14 to 5.0.18. - [Release notes](https://github.com/npgsql/npgsql/releases) - [Commits](https://github.com/npgsql/npgsql/compare/v5.0.14...v5.0.18) --- updated-dependencies: - dependency-name: Npgsql dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .../WorkflowCore.Persistence.PostgreSQL.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index c49965ef2..be939451b 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -47,7 +47,7 @@ - + All From 6a0cb88aa7dddb3e5fbff1c9d41d01353c55818e Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 14 Aug 2024 13:12:21 -0700 Subject: [PATCH 292/342] Update dotnet.yml --- .github/workflows/dotnet.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index cabbec099..b0c3ab704 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -34,6 +34,7 @@ jobs: dotnet-version: | 3.1.x 6.0.x + 8.0.x - name: Restore dependencies run: dotnet restore - name: Build @@ -50,6 +51,7 @@ jobs: dotnet-version: | 3.1.x 6.0.x + 8.0.x - name: Restore dependencies run: dotnet restore - name: Build @@ -66,6 +68,7 @@ jobs: dotnet-version: | 3.1.x 6.0.x + 8.0.x - name: Restore dependencies run: dotnet restore - name: Build @@ -82,6 +85,7 @@ jobs: dotnet-version: | 3.1.x 6.0.x + 8.0.x - name: Restore dependencies run: dotnet restore - name: Build @@ -98,6 +102,7 @@ jobs: dotnet-version: | 3.1.x 6.0.x + 8.0.x - name: Restore dependencies run: dotnet restore - name: Build @@ -114,6 +119,7 @@ jobs: dotnet-version: | 3.1.x 6.0.x + 8.0.x - name: Restore dependencies run: dotnet restore - name: Build @@ -130,6 +136,7 @@ jobs: dotnet-version: | 3.1.x 6.0.x + 8.0.x - name: Restore dependencies run: dotnet restore - name: Build From b90b61c82e618d16435a1812315a5efea80d5bf0 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 10 Sep 2024 09:30:50 -0700 Subject: [PATCH 293/342] oracle version --- .../WorkflowCore.Persistence.Oracle.csproj | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj b/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj index 1c80bad68..898f7fab2 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj +++ b/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj @@ -19,21 +19,18 @@ - - all - runtime; build; native; contentfiles; analyzers - + + + All + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + - 6.21.61 - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive + 7.21.13 - + From 3f12604f911f2c8e40523c99ba8acc5d3feb9710 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Tue, 10 Sep 2024 09:39:37 -0700 Subject: [PATCH 294/342] Update Directory.Build.props --- src/Directory.Build.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 2a61e9808..cb377a989 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -5,9 +5,9 @@ git https://github.com/danielgerlag/workflow-core.git 3.10.0 - 3.10.0.0 - 3.10.0.0 + 3.11.0.0 + 3.11.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.10.0 + 3.11.0 From 0f91b37284ad5456e71af7ee709b34a45132c6d4 Mon Sep 17 00:00:00 2001 From: dsbegnoche Date: Wed, 23 Oct 2024 14:16:55 -0500 Subject: [PATCH 295/342] upgrade to mongo 2.30 --- .../WorkflowCore.Persistence.MongoDB.csproj | 2 +- .../WorkflowCore.Tests.MongoDB.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj index e55685a2e..66cde70ce 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj +++ b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj @@ -22,7 +22,7 @@ - + diff --git a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj index d30af9bec..77638e86b 100644 --- a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj +++ b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj @@ -22,7 +22,7 @@ - + From db61af319b04acdec151dbde3b2b797821ad9767 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Fri, 25 Oct 2024 08:32:24 -0700 Subject: [PATCH 296/342] Create CODEOWNERS --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..a7923835b --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @danielgerlag @glucaci From ef17734ecc6995e8005738e1a8c4596deaa14b4f Mon Sep 17 00:00:00 2001 From: Ankur Charan Date: Mon, 30 Dec 2024 13:26:55 +0000 Subject: [PATCH 297/342] add cosmos mi --- .../ServiceCollectionExtensions.cs | 19 +++++++++++++++++++ .../Services/CosmosClientFactory.cs | 5 +++++ 2 files changed, 24 insertions(+) diff --git a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs index d6aec277d..aa3d5f106 100644 --- a/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Providers.Azure/ServiceCollectionExtensions.cs @@ -46,5 +46,24 @@ public static WorkflowOptions UseCosmosDbPersistence( options.UsePersistence(sp => new CosmosDbPersistenceProvider(sp.GetService(), databaseId, sp.GetService(), cosmosDbStorageOptions)); return options; } + + public static WorkflowOptions UseCosmosDbPersistence( + this WorkflowOptions options, + CosmosClient client, + string databaseId, + CosmosDbStorageOptions cosmosDbStorageOptions = null, + CosmosClientOptions clientOptions = null) + { + if (cosmosDbStorageOptions == null) + { + cosmosDbStorageOptions = new CosmosDbStorageOptions(); + } + + options.Services.AddSingleton(sp => new CosmosClientFactory(client)); + options.Services.AddTransient(sp => new CosmosDbProvisioner(sp.GetService(), cosmosDbStorageOptions)); + options.Services.AddSingleton(sp => new WorkflowPurger(sp.GetService(), databaseId, cosmosDbStorageOptions)); + options.UsePersistence(sp => new CosmosDbPersistenceProvider(sp.GetService(), databaseId, sp.GetService(), cosmosDbStorageOptions)); + return options; + } } } diff --git a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs index ac5dc7f4a..2128d45e0 100644 --- a/src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs +++ b/src/providers/WorkflowCore.Providers.Azure/Services/CosmosClientFactory.cs @@ -15,6 +15,11 @@ public CosmosClientFactory(string connectionString, CosmosClientOptions clientOp _client = new CosmosClient(connectionString, clientOptions); } + public CosmosClientFactory(CosmosClient client) + { + _client = client; + } + public CosmosClient GetCosmosClient() { return this._client; From 636ca0a03fb33ef6d1656558ddec5baaa7d6d476 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 1 Jan 2025 19:08:29 -0800 Subject: [PATCH 298/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index cb377a989..d7f79daf7 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.10.0 - 3.11.0.0 - 3.11.0.0 + 3.12.0 + 3.12.0.0 + 3.12.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.11.0 + 3.12.0 From fc7989085e0e9d77259fecf49ff7eee497ede408 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Thu, 2 Jan 2025 18:31:21 -0800 Subject: [PATCH 299/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index d7f79daf7..63b3fef6f 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.12.0 - 3.12.0.0 - 3.12.0.0 + 3.13.0 + 3.13.0.0 + 3.13.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.12.0 + 3.13.0 From 8f652f07849ec19b26ff6a366c00e371483f9529 Mon Sep 17 00:00:00 2001 From: Jordan Wallwork Date: Fri, 3 Jan 2025 14:22:10 +0000 Subject: [PATCH 300/342] Upgrade Persistence.SqlServer to use net9 --- .github/workflows/dotnet.yml | 1 + .../WorkflowCore.Persistence.SqlServer.csproj | 13 ++++++++++++- test/Directory.Build.props | 2 +- .../WorkflowCore.Tests.SqlServer.csproj | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index b0c3ab704..b311e62d1 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -120,6 +120,7 @@ jobs: 3.1.x 6.0.x 8.0.x + 9.0.x - name: Restore dependencies run: dotnet restore - name: Build diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index cfef6609f..2c4f5cee3 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -4,7 +4,7 @@ Workflow Core SQL Server Persistence Provider 1.8.0 Daniel Gerlag - netstandard2.1;net6.0;net8.0 + netstandard2.1;net6.0;net8.0;net9.0 WorkflowCore.Persistence.SqlServer WorkflowCore.Persistence.SqlServer workflow;.NET;Core;state machine;WorkflowCore @@ -45,6 +45,17 @@ + + + + All + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 2dc7c95f9..0a98ed47a 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -18,7 +18,7 @@ - + \ No newline at end of file diff --git a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj index bf9557556..11b6c00e2 100644 --- a/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj +++ b/test/WorkflowCore.Tests.SqlServer/WorkflowCore.Tests.SqlServer.csproj @@ -1,7 +1,7 @@  - net6.0;net8.0 + net6.0;net8.0;net9.0 From 1397060a078f9a228cb02a78882bc0091eced3f8 Mon Sep 17 00:00:00 2001 From: Jordan Wallwork Date: Wed, 15 Jan 2025 16:31:44 +0000 Subject: [PATCH 301/342] Use later versions of actions to support .net9 --- .github/workflows/dotnet.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index b311e62d1..1a6532ae7 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -112,9 +112,9 @@ jobs: SQLServer-Tests: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v4 with: dotnet-version: | 3.1.x From 09cd773cdc22c161221e50928e813752fddadfa7 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Sat, 18 Jan 2025 07:58:27 -0800 Subject: [PATCH 302/342] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 53ef98486..1eeb0fa66 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Workflow Core [![Build status](https://ci.appveyor.com/api/projects/status/xnby6p5v4ur04u76?svg=true)](https://ci.appveyor.com/project/danielgerlag/workflow-core) +[](https://api.gitsponsors.com/api/badge/link?p=xj6mObb7nZAJGyuABfd8nD5XWf3SE4oUfw0vmCgSiJeIfNlzJAej0FWX8oFdYm6D7bvZpCf6qANVBNPWid4dRQ==) Workflow Core is a light weight embeddable workflow engine targeting .NET Standard. Think: long running processes with multiple tasks that need to track state. It supports pluggable persistence and concurrency providers to allow for multi-node clusters. From 4a260b096b0273bd322d33c083487740fd900fc1 Mon Sep 17 00:00:00 2001 From: Florian Rohrer Date: Thu, 12 Jun 2025 17:39:27 +0200 Subject: [PATCH 303/342] Upgrade MongoDB driver to 3.4.0 --- .../Services/MongoPersistenceProvider.cs | 2 +- .../WorkflowCore.Persistence.MongoDB.csproj | 4 ++-- test/Directory.Build.props | 13 +++---------- test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs | 9 +++++++-- .../WorkflowCore.Tests.MongoDB.csproj | 6 +++--- 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs index d38ded2a5..a72340d68 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs +++ b/src/providers/WorkflowCore.Persistence.MongoDB/Services/MongoPersistenceProvider.cs @@ -197,7 +197,7 @@ public async Task> GetWorkflowInstances(IEnumerabl public async Task> GetWorkflowInstances(WorkflowStatus? status, string type, DateTime? createdFrom, DateTime? createdTo, int skip, int take) { - IMongoQueryable result = WorkflowInstances.AsQueryable(); + IQueryable result = WorkflowInstances.AsQueryable(); if (status.HasValue) result = result.Where(x => x.Status == status.Value); diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj index 66cde70ce..5dfdf800f 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj +++ b/src/providers/WorkflowCore.Persistence.MongoDB/WorkflowCore.Persistence.MongoDB.csproj @@ -3,7 +3,7 @@ Workflow Core MongoDB Persistence Provider Daniel Gerlag - netstandard2.0 + netstandard2.1 WorkflowCore.Persistence.MongoDB WorkflowCore.Persistence.MongoDB workflow;.NET;Core;state machine;WorkflowCore;MongoDB;Mongo @@ -22,7 +22,7 @@ - + diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 0a98ed47a..cdb7e1676 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -6,19 +6,12 @@ - - - + + + - - - - - - - \ No newline at end of file diff --git a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs index df281ce29..e5c18b341 100644 --- a/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs +++ b/test/WorkflowCore.Tests.MongoDB/MongoDockerSetup.cs @@ -1,25 +1,30 @@ using System; using System.Threading.Tasks; using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; using Squadron; +using WorkflowCore.UnitTests; using Xunit; namespace WorkflowCore.Tests.MongoDB { public class MongoDockerSetup : IAsyncLifetime { - private readonly MongoResource _mongoResource; + private readonly MongoReplicaSetResource _mongoResource; public static string ConnectionString { get; set; } public MongoDockerSetup() { - _mongoResource = new MongoResource(); + _mongoResource = new MongoReplicaSetResource(); } public async Task InitializeAsync() { await _mongoResource.InitializeAsync(); ConnectionString = _mongoResource.ConnectionString; + BsonSerializer.TryRegisterSerializer(new ObjectSerializer(type => + ObjectSerializer.DefaultAllowedTypes(type) || type.FullName.StartsWith("WorkflowCore."))); } public Task DisposeAsync() diff --git a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj index 77638e86b..0bffc02e8 100644 --- a/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj +++ b/test/WorkflowCore.Tests.MongoDB/WorkflowCore.Tests.MongoDB.csproj @@ -7,7 +7,7 @@ false false false - net6.0 + net8.0 @@ -21,8 +21,8 @@ - - + + From 5c683ff7c8ab1e0702c4e6aad0d4ace0376d0ea3 Mon Sep 17 00:00:00 2001 From: Florian Rohrer Date: Mon, 16 Jun 2025 11:07:58 +0200 Subject: [PATCH 304/342] Update .NET version in workflow to include 9.0.x, drop 3.1 --- .github/workflows/dotnet.yml | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 1a6532ae7..a3b389069 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -15,9 +15,9 @@ jobs: uses: actions/setup-dotnet@v1 with: dotnet-version: | - 3.1.x 6.0.x 8.0.x + 9.0.x - name: Restore dependencies run: dotnet restore - name: Build @@ -31,10 +31,10 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: | - 3.1.x + dotnet-version: | 6.0.x 8.0.x + 9.0.x - name: Restore dependencies run: dotnet restore - name: Build @@ -48,10 +48,10 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: | - 3.1.x + dotnet-version: | 6.0.x 8.0.x + 9.0.x - name: Restore dependencies run: dotnet restore - name: Build @@ -65,10 +65,10 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: | - 3.1.x + dotnet-version: | 6.0.x 8.0.x + 9.0.x - name: Restore dependencies run: dotnet restore - name: Build @@ -82,10 +82,10 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: | - 3.1.x + dotnet-version: | 6.0.x 8.0.x + 9.0.x - name: Restore dependencies run: dotnet restore - name: Build @@ -99,10 +99,10 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: | - 3.1.x + dotnet-version: | 6.0.x 8.0.x + 9.0.x - name: Restore dependencies run: dotnet restore - name: Build @@ -114,10 +114,9 @@ jobs: steps: - uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v1 with: - dotnet-version: | - 3.1.x + dotnet-version: | 6.0.x 8.0.x 9.0.x @@ -134,10 +133,10 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: | - 3.1.x + dotnet-version: | 6.0.x 8.0.x + 9.0.x - name: Restore dependencies run: dotnet restore - name: Build From b5802797070acb93ac1c213d3120f35976787662 Mon Sep 17 00:00:00 2001 From: Florian Rohrer Date: Mon, 16 Jun 2025 11:12:04 +0200 Subject: [PATCH 305/342] fix typo in documentation --- src/providers/WorkflowCore.Persistence.MongoDB/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Persistence.MongoDB/README.md b/src/providers/WorkflowCore.Persistence.MongoDB/README.md index 911d8a9e4..9668e393d 100644 --- a/src/providers/WorkflowCore.Persistence.MongoDB/README.md +++ b/src/providers/WorkflowCore.Persistence.MongoDB/README.md @@ -24,7 +24,7 @@ By default (to maintain backwards compatibility), the state object is serialized This approach has some limitations, for example you cannot control which types will be used in MongoDB for particular fields and you cannot use basic types that are not present in JSON (decimal, timestamp, etc). To eliminate these limitations, you can use a direct object -> BSON serialization and utilize all serialization possibilities that MongoDb driver provides. You can read more in the [MongoDb CSharp documentation](https://mongodb.github.io/mongo-csharp-driver/1.11/serialization/). -To enable direct serilization you need to register a class map for you state class somewhere in your startup process before you run `WorkflowHost`. +To enable direct serialization you need to register a class map for you state class somewhere in your startup process before you run `WorkflowHost`. ```C# private void RunWorkflow() From a37e3e3379ace5c1afffc39902e8422c5c8abab6 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Thu, 19 Jun 2025 09:36:42 -0700 Subject: [PATCH 306/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 63b3fef6f..061235f4f 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.13.0 - 3.13.0.0 - 3.13.0.0 + 3.14.0 + 3.14.0.0 + 3.14.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.13.0 + 3.14.0 From 5c5c8d676b185e75368af1703003f5652142df95 Mon Sep 17 00:00:00 2001 From: Henrique Pagno de Lima Date: Wed, 9 Jul 2025 21:56:59 -0300 Subject: [PATCH 307/342] Added support for .NET 8.0 for Oracle Persistence, removed SqlServer packages dependencies, cleaned code of the files, plus some minor adjustments. Added Oracle as a persistence option in readme. --- README.md | 1 + .../MigrationContextFactory.cs | 5 +- .../OracleContext.cs | 2 - .../OracleContextFactory.cs | 3 - .../ServiceCollectionExtensions.cs | 9 +-- .../WorkflowCore.Persistence.Oracle.csproj | 78 +++++++++++-------- 6 files changed, 49 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 1eeb0fa66..0429fb597 100644 --- a/README.md +++ b/README.md @@ -140,6 +140,7 @@ There are several persistence providers available as separate Nuget packages. * [Sqlite](src/providers/WorkflowCore.Persistence.Sqlite) * [MySQL](src/providers/WorkflowCore.Persistence.MySQL) * [Redis](src/providers/WorkflowCore.Providers.Redis) +* [Oracle](src/providers/WorkflowCore.Persistence.Oracle) ## Search diff --git a/src/providers/WorkflowCore.Persistence.Oracle/MigrationContextFactory.cs b/src/providers/WorkflowCore.Persistence.Oracle/MigrationContextFactory.cs index 687109711..f5a37a5f9 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/MigrationContextFactory.cs +++ b/src/providers/WorkflowCore.Persistence.Oracle/MigrationContextFactory.cs @@ -1,7 +1,4 @@ -using System; -using System.Linq; - -using Microsoft.EntityFrameworkCore.Design; +using Microsoft.EntityFrameworkCore.Design; namespace WorkflowCore.Persistence.Oracle { diff --git a/src/providers/WorkflowCore.Persistence.Oracle/OracleContext.cs b/src/providers/WorkflowCore.Persistence.Oracle/OracleContext.cs index b8fadcdf7..d6619c4b3 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/OracleContext.cs +++ b/src/providers/WorkflowCore.Persistence.Oracle/OracleContext.cs @@ -1,8 +1,6 @@ using System; -using System.Linq; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Oracle.EntityFrameworkCore.Infrastructure; diff --git a/src/providers/WorkflowCore.Persistence.Oracle/OracleContextFactory.cs b/src/providers/WorkflowCore.Persistence.Oracle/OracleContextFactory.cs index 54c70d6dc..e2d9c6e1a 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/OracleContextFactory.cs +++ b/src/providers/WorkflowCore.Persistence.Oracle/OracleContextFactory.cs @@ -1,7 +1,4 @@ using System; -using System.Linq; - -using Microsoft.EntityFrameworkCore.Infrastructure; using Oracle.EntityFrameworkCore.Infrastructure; diff --git a/src/providers/WorkflowCore.Persistence.Oracle/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.Persistence.Oracle/ServiceCollectionExtensions.cs index 4a46b0e5c..704916fbe 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.Persistence.Oracle/ServiceCollectionExtensions.cs @@ -1,7 +1,4 @@ using System; -using System.Linq; - -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; using Oracle.EntityFrameworkCore.Infrastructure; @@ -14,10 +11,10 @@ namespace WorkflowCore.Persistence.Oracle { public static class ServiceCollectionExtensions { - public static WorkflowOptions UseOracle(this WorkflowOptions options, string connectionString, bool canCreateDB, bool canMigrateDB, Action mysqlOptionsAction = null) + public static WorkflowOptions UseOracle(this WorkflowOptions options, string connectionString, bool canCreateDB, bool canMigrateDB, Action oracleOptionsAction = null) { - options.UsePersistence(sp => new EntityFrameworkPersistenceProvider(new OracleContextFactory(connectionString, mysqlOptionsAction), canCreateDB, canMigrateDB)); - options.Services.AddTransient(sp => new WorkflowPurger(new OracleContextFactory(connectionString, mysqlOptionsAction))); + options.UsePersistence(sp => new EntityFrameworkPersistenceProvider(new OracleContextFactory(connectionString, oracleOptionsAction), canCreateDB, canMigrateDB)); + options.Services.AddTransient(sp => new WorkflowPurger(new OracleContextFactory(connectionString, oracleOptionsAction))); return options; } } diff --git a/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj b/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj index 898f7fab2..e49e1a88a 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj +++ b/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj @@ -1,40 +1,50 @@  - - Workflow Core Oracle Persistence Provider - 1.0.0 - Christian Jundt - net6.0 - WorkflowCore.Persistence.Oracle - WorkflowCore.Persistence.Oracle - workflow;.NET;Core;state machine;WorkflowCore;Oracle - https://github.com/danielgerlag/workflow-core - https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md - git - https://github.com/danielgerlag/workflow-core.git - false - false - false - Provides support to persist workflows running on Workflow Core to a Oracle database. - + + Workflow Core Oracle Persistence Provider + 1.0.0 + Christian Jundt + net6.0;net8.0 + WorkflowCore.Persistence.Oracle + WorkflowCore.Persistence.Oracle + workflow;.NET;Core;state machine;WorkflowCore;Oracle + https://github.com/danielgerlag/workflow-core + https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md + git + https://github.com/danielgerlag/workflow-core.git + false + false + false + Provides support to persist workflows running on Workflow Core to a Oracle database. + - - - - All - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - 7.21.13 - - + + + All + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + - - - - + + + All + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + 7.21.13 + + + + + + + From 7e3cfb471bfa2b8ec27490af89769c9a5e8aedaf Mon Sep 17 00:00:00 2001 From: Henrique Pagno de Lima Date: Thu, 10 Jul 2025 21:26:43 -0300 Subject: [PATCH 308/342] Fixed Oracle tests adding TestContainers. Minor code adjustments. Added net8.0 test support for Oracle. --- .../OraclePersistenceProviderFixture.cs | 8 ++---- test/WorkflowCore.Tests.Oracle/OracleSetup.cs | 28 ++++++++++++------- .../Scenarios/OracleActivityScenario.cs | 6 ++-- .../Scenarios/OracleBasicScenario.cs | 6 ++-- .../Scenarios/OracleDataScenario.cs | 6 ++-- .../Scenarios/OracleDelayScenario.cs | 3 +- .../Scenarios/OracleDynamicDataScenario.cs | 4 +-- .../Scenarios/OracleEventScenario.cs | 6 ++-- .../Scenarios/OracleForeachScenario.cs | 6 ++-- .../Scenarios/OracleForkScenario.cs | 6 ++-- .../Scenarios/OracleIfScenario.cs | 6 ++-- .../Scenarios/OracleRetrySagaScenario.cs | 6 ++-- .../Scenarios/OracleSagaScenario.cs | 6 ++-- .../Scenarios/OracleUserScenario.cs | 6 ++-- .../Scenarios/OracleWhenScenario.cs | 6 ++-- .../Scenarios/OracleWhileScenario.cs | 6 ++-- .../WorkflowCore.Tests.Oracle.csproj | 6 +++- 17 files changed, 52 insertions(+), 69 deletions(-) diff --git a/test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs b/test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs index c4445f005..cd9eefdd5 100644 --- a/test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs +++ b/test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs @@ -1,8 +1,6 @@ -using System; -using WorkflowCore.Interface; +using WorkflowCore.Interface; using WorkflowCore.Persistence.EntityFramework.Services; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using WorkflowCore.UnitTests; using Xunit; using Xunit.Abstractions; @@ -12,10 +10,10 @@ namespace WorkflowCore.Tests.Oracle [Collection("Oracle collection")] public class OraclePersistenceProviderFixture : BasePersistenceFixture { - private readonly IPersistenceProvider _subject; + private readonly EntityFrameworkPersistenceProvider _subject; protected override IPersistenceProvider Subject => _subject; - public OraclePersistenceProviderFixture(OracleDockerSetup dockerSetup, ITestOutputHelper output) + public OraclePersistenceProviderFixture(ITestOutputHelper output) { output.WriteLine($"Connecting on {OracleDockerSetup.ConnectionString}"); _subject = new EntityFrameworkPersistenceProvider(new OracleContextFactory(OracleDockerSetup.ConnectionString), true, true); diff --git a/test/WorkflowCore.Tests.Oracle/OracleSetup.cs b/test/WorkflowCore.Tests.Oracle/OracleSetup.cs index 8b35d9aa2..a5ee262ec 100644 --- a/test/WorkflowCore.Tests.Oracle/OracleSetup.cs +++ b/test/WorkflowCore.Tests.Oracle/OracleSetup.cs @@ -1,26 +1,34 @@ -using System; -using System.Threading.Tasks; - +using System.Threading.Tasks; +using Testcontainers.Oracle; using Xunit; namespace WorkflowCore.Tests.Oracle { public class OracleDockerSetup : IAsyncLifetime { - public static string ConnectionString => "Data Source=(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = ORCLPDB1) ) );User ID=TEST_WF;Password=test;"; + private readonly OracleContainer _oracleContainer; - public async Task InitializeAsync() + public static string ConnectionString { get; private set; } + + public OracleDockerSetup() { + _oracleContainer = new OracleBuilder() + .WithImage("gvenzl/oracle-free:latest") + .WithUsername("TEST_WF") + .WithPassword("test") + .Build(); } - public Task DisposeAsync() + public async Task InitializeAsync() { - return Task.CompletedTask; + await _oracleContainer.StartAsync(); + // Build connection string manually since TestContainers might not provide Oracle-specific format + ConnectionString = $"Data Source=localhost:{_oracleContainer.GetMappedPublicPort(1521)}/FREEPDB1;User Id=TEST_WF;Password=test;"; } + + public async Task DisposeAsync() => await _oracleContainer.DisposeAsync(); } [CollectionDefinition("Oracle collection")] - public class OracleCollection : ICollectionFixture - { - } + public class OracleCollection : ICollectionFixture { } } \ No newline at end of file diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleActivityScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleActivityScenario.cs index eeae8ea66..7bf8ae2d6 100644 --- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleActivityScenario.cs +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleActivityScenario.cs @@ -1,8 +1,6 @@ -using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using Xunit; @@ -10,7 +8,7 @@ namespace WorkflowCore.Tests.Oracle.Scenarios { [Collection("Oracle collection")] public class OracleActivityScenario : ActivityScenario - { + { protected override void ConfigureServices(IServiceCollection services) { services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleBasicScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleBasicScenario.cs index 8cb898583..a7f8bb940 100644 --- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleBasicScenario.cs +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleBasicScenario.cs @@ -1,8 +1,6 @@ -using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using Xunit; @@ -10,7 +8,7 @@ namespace WorkflowCore.Tests.Oracle.Scenarios { [Collection("Oracle collection")] public class OracleBasicScenario : BasicScenario - { + { protected override void ConfigureServices(IServiceCollection services) { services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDataScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDataScenario.cs index f71630c93..136b54a3e 100644 --- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDataScenario.cs +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDataScenario.cs @@ -1,8 +1,6 @@ -using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using Xunit; @@ -10,7 +8,7 @@ namespace WorkflowCore.Tests.Oracle.Scenarios { [Collection("Oracle collection")] public class OracleDataScenario : DataIOScenario - { + { protected override void ConfigureServices(IServiceCollection services) { services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs index 55062f0c3..22a582f0d 100644 --- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDelayScenario.cs @@ -2,7 +2,6 @@ using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using Xunit; @@ -10,7 +9,7 @@ namespace WorkflowCore.Tests.Oracle.Scenarios { [Collection("Oracle collection")] public class OracleDelayScenario : DelayScenario - { + { protected override void ConfigureServices(IServiceCollection services) { services.AddWorkflow(cfg => diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDynamicDataScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDynamicDataScenario.cs index e59f51d51..5ab8b940b 100644 --- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDynamicDataScenario.cs +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleDynamicDataScenario.cs @@ -1,8 +1,6 @@ -using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using Xunit; diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleEventScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleEventScenario.cs index ac987c341..a38290065 100644 --- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleEventScenario.cs +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleEventScenario.cs @@ -1,8 +1,6 @@ -using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using Xunit; @@ -10,7 +8,7 @@ namespace WorkflowCore.Tests.Oracle.Scenarios { [Collection("Oracle collection")] public class OracleEventScenario : EventScenario - { + { protected override void ConfigureServices(IServiceCollection services) { services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForeachScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForeachScenario.cs index fb2fcc965..023920ba1 100644 --- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForeachScenario.cs +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForeachScenario.cs @@ -1,8 +1,6 @@ -using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using Xunit; @@ -10,7 +8,7 @@ namespace WorkflowCore.Tests.Oracle.Scenarios { [Collection("Oracle collection")] public class OracleForeachScenario : ForeachScenario - { + { protected override void ConfigureServices(IServiceCollection services) { services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForkScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForkScenario.cs index d525de700..bbe85a909 100644 --- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForkScenario.cs +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleForkScenario.cs @@ -1,8 +1,6 @@ -using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using Xunit; @@ -10,7 +8,7 @@ namespace WorkflowCore.Tests.Oracle.Scenarios { [Collection("Oracle collection")] public class OracleForkScenario : ForkScenario - { + { protected override void Configure(IServiceCollection services) { services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleIfScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleIfScenario.cs index c090f89d1..cab8004bd 100644 --- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleIfScenario.cs +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleIfScenario.cs @@ -1,8 +1,6 @@ -using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using Xunit; @@ -10,7 +8,7 @@ namespace WorkflowCore.Tests.Oracle.Scenarios { [Collection("Oracle collection")] public class OracleIfScenario : IfScenario - { + { protected override void ConfigureServices(IServiceCollection services) { services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleRetrySagaScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleRetrySagaScenario.cs index 01c651a7c..21bf5dbef 100644 --- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleRetrySagaScenario.cs +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleRetrySagaScenario.cs @@ -1,8 +1,6 @@ -using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using Xunit; @@ -10,7 +8,7 @@ namespace WorkflowCore.Tests.Oracle.Scenarios { [Collection("Oracle collection")] public class OracleRetrySagaScenario : RetrySagaScenario - { + { protected override void ConfigureServices(IServiceCollection services) { services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleSagaScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleSagaScenario.cs index 7775638c2..ea093b222 100644 --- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleSagaScenario.cs +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleSagaScenario.cs @@ -1,8 +1,6 @@ -using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using Xunit; @@ -10,7 +8,7 @@ namespace WorkflowCore.Tests.Oracle.Scenarios { [Collection("Oracle collection")] public class OracleSagaScenario : SagaScenario - { + { protected override void ConfigureServices(IServiceCollection services) { services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleUserScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleUserScenario.cs index 0e5861f6d..60ab568b2 100644 --- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleUserScenario.cs +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleUserScenario.cs @@ -1,8 +1,6 @@ -using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using Xunit; @@ -10,7 +8,7 @@ namespace WorkflowCore.Tests.Oracle.Scenarios { [Collection("Oracle collection")] public class OracleUserScenario : UserScenario - { + { protected override void ConfigureServices(IServiceCollection services) { services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhenScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhenScenario.cs index b8671695e..d12490f59 100644 --- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhenScenario.cs +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhenScenario.cs @@ -1,8 +1,6 @@ -using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using Xunit; @@ -10,7 +8,7 @@ namespace WorkflowCore.Tests.Oracle.Scenarios { [Collection("Oracle collection")] public class OracleWhenScenario : WhenScenario - { + { protected override void ConfigureServices(IServiceCollection services) { services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); diff --git a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhileScenario.cs b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhileScenario.cs index 0b4b01467..45f5eebdd 100644 --- a/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhileScenario.cs +++ b/test/WorkflowCore.Tests.Oracle/Scenarios/OracleWhileScenario.cs @@ -1,8 +1,6 @@ -using System; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using WorkflowCore.IntegrationTests.Scenarios; using WorkflowCore.Persistence.Oracle; -using WorkflowCore.Tests.Oracle; using Xunit; @@ -10,7 +8,7 @@ namespace WorkflowCore.Tests.Oracle.Scenarios { [Collection("Oracle collection")] public class OracleWhileScenario : WhileScenario - { + { protected override void ConfigureServices(IServiceCollection services) { services.AddWorkflow(x => x.UseOracle(OracleDockerSetup.ConnectionString, true, true)); diff --git a/test/WorkflowCore.Tests.Oracle/WorkflowCore.Tests.Oracle.csproj b/test/WorkflowCore.Tests.Oracle/WorkflowCore.Tests.Oracle.csproj index db77aa957..b3b68406c 100644 --- a/test/WorkflowCore.Tests.Oracle/WorkflowCore.Tests.Oracle.csproj +++ b/test/WorkflowCore.Tests.Oracle/WorkflowCore.Tests.Oracle.csproj @@ -1,7 +1,7 @@  - net6.0 + net6.0;net8.0 WorkflowCore.Tests.Oracle WorkflowCore.Tests.Oracle true @@ -10,6 +10,10 @@ false + + + + From df17d346fe28c30e12bc5c29ca90c7798f0970ec Mon Sep 17 00:00:00 2001 From: Henrique Pagno de Lima Date: Thu, 10 Jul 2025 21:28:08 -0300 Subject: [PATCH 309/342] Added Oracle tests to the github pipeline. --- .github/workflows/dotnet.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index a3b389069..d99947484 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -143,3 +143,19 @@ jobs: run: dotnet build --no-restore - name: Elasticsearch Tests run: dotnet test test/WorkflowCore.Tests.Elasticsearch --no-build --verbosity normal -p:ParallelizeTestCollections=false + Oracle-Tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: | + 6.0.x + 8.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Oracle Tests + run: dotnet test test/WorkflowCore.Tests.Oracle --no-build --verbosity normal -p:ParallelizeTestCollections=false From cb9fd8402693171089fa45b22894b17bea569ff2 Mon Sep 17 00:00:00 2001 From: Henrique Pagno de Lima Date: Thu, 10 Jul 2025 21:37:52 -0300 Subject: [PATCH 310/342] Added minor improvements to the Oracle Persistence readme. --- .../WorkflowCore.Persistence.Oracle/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/providers/WorkflowCore.Persistence.Oracle/README.md b/src/providers/WorkflowCore.Persistence.Oracle/README.md index 0e4957eea..c29fbebbf 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/README.md +++ b/src/providers/WorkflowCore.Persistence.Oracle/README.md @@ -17,3 +17,15 @@ Use the .UseOracle extension method when building your service provider. ```C# services.AddWorkflow(x => x.UseOracle(@"Server=127.0.0.1;Database=workflow;User=root;Password=password;", true, true)); ``` + +You can also add specific database version compability if needed. + +```C# +services.AddWorkflow(x => + { + x.UseOracle(connectionString, false, true, options => + { + options.UseOracleSQLCompatibility(OracleSQLCompatibility.DatabaseVersion19); + }); + }); +``` \ No newline at end of file From 47e34b2350025d54393bf0481c1e832d0a5f437e Mon Sep 17 00:00:00 2001 From: Henrique Pagno de Lima Date: Fri, 11 Jul 2025 13:26:08 -0300 Subject: [PATCH 311/342] Added Oracle persistence to the docs. --- docs/persistence.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/persistence.md b/docs/persistence.md index 8a7fe55fd..00799090a 100644 --- a/docs/persistence.md +++ b/docs/persistence.md @@ -11,3 +11,4 @@ There are several persistence providers available as separate Nuget packages. * [Amazon DynamoDB](https://github.com/danielgerlag/workflow-core/tree/master/src/providers/WorkflowCore.Providers.AWS) * [Cosmos DB](https://github.com/danielgerlag/workflow-core/tree/master/src/providers/WorkflowCore.Providers.Azure) * [Redis](https://github.com/danielgerlag/workflow-core/tree/master/src/providers/WorkflowCore.Providers.Redis) +* [Oracle](https://github.com/danielgerlag/workflow-core/tree/master/src/providers/WorkflowCore.Persistence.Oracle) \ No newline at end of file From 193c92fa10d285acb69166d71e24d81001f62c9b Mon Sep 17 00:00:00 2001 From: Alexander Kovtik Date: Fri, 11 Jul 2025 19:35:52 +0200 Subject: [PATCH 312/342] Replacing System.Data.SqlClient dependency with Microsoft.Data.SqlClient in WorkflowCore.LockProviders.SqlServer project. --- .../WorkflowCore.LockProviders.SqlServer/SqlLockProvider.cs | 2 +- .../WorkflowCore.LockProviders.SqlServer.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/providers/WorkflowCore.LockProviders.SqlServer/SqlLockProvider.cs b/src/providers/WorkflowCore.LockProviders.SqlServer/SqlLockProvider.cs index 92795d871..8bb0cf5dc 100644 --- a/src/providers/WorkflowCore.LockProviders.SqlServer/SqlLockProvider.cs +++ b/src/providers/WorkflowCore.LockProviders.SqlServer/SqlLockProvider.cs @@ -1,5 +1,5 @@ using System; -using System.Data.SqlClient; +using Microsoft.Data.SqlClient; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using WorkflowCore.Interface; diff --git a/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj b/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj index f703c21ab..4d9702579 100644 --- a/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj +++ b/src/providers/WorkflowCore.LockProviders.SqlServer/WorkflowCore.LockProviders.SqlServer.csproj @@ -8,7 +8,7 @@ - + From c3d8c52827ee5febf7261371b99901653549c3a8 Mon Sep 17 00:00:00 2001 From: Henrique Pagno de Lima Date: Sun, 3 Aug 2025 21:30:25 -0300 Subject: [PATCH 313/342] Fixed missing OracleDockerSetup dependency injection in test fixture. Fixed a word in readme. Added .NET 9.0.x SDK to Oracle-Tests workflow job. --- .github/workflows/dotnet.yml | 1 + src/providers/WorkflowCore.Persistence.Oracle/README.md | 2 +- .../OraclePersistenceProviderFixture.cs | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index d99947484..83e247208 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -153,6 +153,7 @@ jobs: dotnet-version: | 6.0.x 8.0.x + 9.0.x - name: Restore dependencies run: dotnet restore - name: Build diff --git a/src/providers/WorkflowCore.Persistence.Oracle/README.md b/src/providers/WorkflowCore.Persistence.Oracle/README.md index c29fbebbf..1dd74ee7c 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/README.md +++ b/src/providers/WorkflowCore.Persistence.Oracle/README.md @@ -18,7 +18,7 @@ Use the .UseOracle extension method when building your service provider. services.AddWorkflow(x => x.UseOracle(@"Server=127.0.0.1;Database=workflow;User=root;Password=password;", true, true)); ``` -You can also add specific database version compability if needed. +You can also add specific database version compatibility if needed. ```C# services.AddWorkflow(x => diff --git a/test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs b/test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs index cd9eefdd5..a87c11bad 100644 --- a/test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs +++ b/test/WorkflowCore.Tests.Oracle/OraclePersistenceProviderFixture.cs @@ -13,7 +13,7 @@ public class OraclePersistenceProviderFixture : BasePersistenceFixture private readonly EntityFrameworkPersistenceProvider _subject; protected override IPersistenceProvider Subject => _subject; - public OraclePersistenceProviderFixture(ITestOutputHelper output) + public OraclePersistenceProviderFixture(OracleDockerSetup dockerSetup, ITestOutputHelper output) { output.WriteLine($"Connecting on {OracleDockerSetup.ConnectionString}"); _subject = new EntityFrameworkPersistenceProvider(new OracleContextFactory(OracleDockerSetup.ConnectionString), true, true); From 041e7aa70dda4bbf5fdbee98ea250d0e75e66584 Mon Sep 17 00:00:00 2001 From: yi_Xu Date: Thu, 7 Aug 2025 16:49:00 +0800 Subject: [PATCH 314/342] fix: use timestamp with time zone in PostgreSQL --- ...hangeDataTimeTypeForPostgreSQL.Designer.cs | 377 ++++++++++++++++++ ...7084543_ChangeDataTimeTypeForPostgreSQL.cs | 191 +++++++++ ...ostgresPersistenceProviderModelSnapshot.cs | 62 +-- .../PostgresContext.cs | 48 +++ 4 files changed, 652 insertions(+), 26 deletions(-) create mode 100644 src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDataTimeTypeForPostgreSQL.Designer.cs create mode 100644 src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDataTimeTypeForPostgreSQL.cs diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDataTimeTypeForPostgreSQL.Designer.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDataTimeTypeForPostgreSQL.Designer.cs new file mode 100644 index 000000000..407a461da --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDataTimeTypeForPostgreSQL.Designer.cs @@ -0,0 +1,377 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using WorkflowCore.Persistence.PostgreSQL; + +#nullable disable + +namespace WorkflowCore.Persistence.PostgreSQL.Migrations +{ + [DbContext(typeof(PostgresContext))] + [Migration("20250807084543_ChangeDataTimeTypeForPostgreSQL")] + partial class ChangeDataTimeTypeForPostgreSQL + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.19") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersistenceId")); + + b.Property("EventData") + .HasColumnType("text"); + + b.Property("EventId") + .HasColumnType("uuid"); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EventTime") + .HasColumnType("timestamp with time zone"); + + b.Property("IsProcessed") + .HasColumnType("boolean"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventId") + .IsUnique(); + + b.HasIndex("EventTime"); + + b.HasIndex("IsProcessed"); + + b.HasIndex("EventName", "EventKey"); + + b.ToTable("Event", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionError", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersistenceId")); + + b.Property("ErrorTime") + .HasColumnType("timestamp with time zone"); + + b.Property("ExecutionPointerId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("WorkflowId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("PersistenceId"); + + b.ToTable("ExecutionError", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersistenceId")); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("Children") + .HasColumnType("text"); + + b.Property("ContextItem") + .HasColumnType("text"); + + b.Property("EndTime") + .HasColumnType("timestamp with time zone"); + + b.Property("EventData") + .HasColumnType("text"); + + b.Property("EventKey") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EventName") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EventPublished") + .HasColumnType("boolean"); + + b.Property("Id") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Outcome") + .HasColumnType("text"); + + b.Property("PersistenceData") + .HasColumnType("text"); + + b.Property("PredecessorId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RetryCount") + .HasColumnType("integer"); + + b.Property("Scope") + .HasColumnType("text"); + + b.Property("SleepUntil") + .HasColumnType("timestamp with time zone"); + + b.Property("StartTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("StepId") + .HasColumnType("integer"); + + b.Property("StepName") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("WorkflowId") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("WorkflowId"); + + b.ToTable("ExecutionPointer", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersistenceId")); + + b.Property("AttributeKey") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("AttributeValue") + .HasColumnType("text"); + + b.Property("ExecutionPointerId") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecutionPointerId"); + + b.ToTable("ExtensionAttribute", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedScheduledCommand", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersistenceId")); + + b.Property("CommandName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Data") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ExecuteTime") + .HasColumnType("bigint"); + + b.HasKey("PersistenceId"); + + b.HasIndex("ExecuteTime"); + + b.HasIndex("CommandName", "Data") + .IsUnique(); + + b.ToTable("ScheduledCommand", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedSubscription", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersistenceId")); + + b.Property("EventKey") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EventName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ExecutionPointerId") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ExternalToken") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ExternalTokenExpiry") + .HasColumnType("timestamp with time zone"); + + b.Property("ExternalWorkerId") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("StepId") + .HasColumnType("integer"); + + b.Property("SubscribeAsOf") + .HasColumnType("timestamp with time zone"); + + b.Property("SubscriptionData") + .HasColumnType("text"); + + b.Property("SubscriptionId") + .HasMaxLength(200) + .HasColumnType("uuid"); + + b.Property("WorkflowId") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("EventKey"); + + b.HasIndex("EventName"); + + b.HasIndex("SubscriptionId") + .IsUnique(); + + b.ToTable("Subscription", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Property("PersistenceId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersistenceId")); + + b.Property("CompleteTime") + .HasColumnType("timestamp with time zone"); + + b.Property("CreateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("InstanceId") + .HasMaxLength(200) + .HasColumnType("uuid"); + + b.Property("NextExecution") + .HasColumnType("bigint"); + + b.Property("Reference") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Version") + .HasColumnType("integer"); + + b.Property("WorkflowDefinitionId") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("PersistenceId"); + + b.HasIndex("InstanceId") + .IsUnique(); + + b.HasIndex("NextExecution"); + + b.ToTable("Workflow", "wfc"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", "Workflow") + .WithMany("ExecutionPointers") + .HasForeignKey("WorkflowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Workflow"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExtensionAttribute", b => + { + b.HasOne("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", "ExecutionPointer") + .WithMany("ExtensionAttributes") + .HasForeignKey("ExecutionPointerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ExecutionPointer"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedExecutionPointer", b => + { + b.Navigation("ExtensionAttributes"); + }); + + modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedWorkflow", b => + { + b.Navigation("ExecutionPointers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDataTimeTypeForPostgreSQL.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDataTimeTypeForPostgreSQL.cs new file mode 100644 index 000000000..1e892fc44 --- /dev/null +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDataTimeTypeForPostgreSQL.cs @@ -0,0 +1,191 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace WorkflowCore.Persistence.PostgreSQL.Migrations +{ + /// + public partial class ChangeDataTimeTypeForPostgreSQL : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "CreateTime", + schema: "wfc", + table: "Workflow", + type: "timestamp with time zone", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "timestamp without time zone"); + + migrationBuilder.AlterColumn( + name: "CompleteTime", + schema: "wfc", + table: "Workflow", + type: "timestamp with time zone", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "timestamp without time zone", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "SubscribeAsOf", + schema: "wfc", + table: "Subscription", + type: "timestamp with time zone", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "timestamp without time zone"); + + migrationBuilder.AlterColumn( + name: "ExternalTokenExpiry", + schema: "wfc", + table: "Subscription", + type: "timestamp with time zone", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "timestamp without time zone", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "StartTime", + schema: "wfc", + table: "ExecutionPointer", + type: "timestamp with time zone", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "timestamp without time zone", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "SleepUntil", + schema: "wfc", + table: "ExecutionPointer", + type: "timestamp with time zone", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "timestamp without time zone", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "EndTime", + schema: "wfc", + table: "ExecutionPointer", + type: "timestamp with time zone", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "timestamp without time zone", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ErrorTime", + schema: "wfc", + table: "ExecutionError", + type: "timestamp with time zone", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "timestamp without time zone"); + + migrationBuilder.AlterColumn( + name: "EventTime", + schema: "wfc", + table: "Event", + type: "timestamp with time zone", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "timestamp without time zone"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "CreateTime", + schema: "wfc", + table: "Workflow", + type: "timestamp without time zone", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone"); + + migrationBuilder.AlterColumn( + name: "CompleteTime", + schema: "wfc", + table: "Workflow", + type: "timestamp without time zone", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "SubscribeAsOf", + schema: "wfc", + table: "Subscription", + type: "timestamp without time zone", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone"); + + migrationBuilder.AlterColumn( + name: "ExternalTokenExpiry", + schema: "wfc", + table: "Subscription", + type: "timestamp without time zone", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "StartTime", + schema: "wfc", + table: "ExecutionPointer", + type: "timestamp without time zone", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "SleepUntil", + schema: "wfc", + table: "ExecutionPointer", + type: "timestamp without time zone", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "EndTime", + schema: "wfc", + table: "ExecutionPointer", + type: "timestamp without time zone", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ErrorTime", + schema: "wfc", + table: "ExecutionError", + type: "timestamp without time zone", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone"); + + migrationBuilder.AlterColumn( + name: "EventTime", + schema: "wfc", + table: "Event", + type: "timestamp without time zone", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone"); + } + } +} diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs index d0278e0c8..0783459b6 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs @@ -6,6 +6,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using WorkflowCore.Persistence.PostgreSQL; +#nullable disable + namespace WorkflowCore.Persistence.PostgreSQL.Migrations { [DbContext(typeof(PostgresContext))] @@ -15,16 +17,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("Relational:MaxIdentifierLength", 63) - .HasAnnotation("ProductVersion", "5.0.8") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasAnnotation("ProductVersion", "8.0.19") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => { b.Property("PersistenceId") .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersistenceId")); b.Property("EventData") .HasColumnType("text"); @@ -41,7 +45,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("character varying(200)"); b.Property("EventTime") - .HasColumnType("timestamp without time zone"); + .HasColumnType("timestamp with time zone"); b.Property("IsProcessed") .HasColumnType("boolean"); @@ -64,11 +68,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("PersistenceId") .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersistenceId")); b.Property("ErrorTime") - .HasColumnType("timestamp without time zone"); + .HasColumnType("timestamp with time zone"); b.Property("ExecutionPointerId") .HasMaxLength(100) @@ -90,8 +95,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("PersistenceId") .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersistenceId")); b.Property("Active") .HasColumnType("boolean"); @@ -103,7 +109,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text"); b.Property("EndTime") - .HasColumnType("timestamp without time zone"); + .HasColumnType("timestamp with time zone"); b.Property("EventData") .HasColumnType("text"); @@ -140,10 +146,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text"); b.Property("SleepUntil") - .HasColumnType("timestamp without time zone"); + .HasColumnType("timestamp with time zone"); b.Property("StartTime") - .HasColumnType("timestamp without time zone"); + .HasColumnType("timestamp with time zone"); b.Property("Status") .HasColumnType("integer"); @@ -169,8 +175,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("PersistenceId") .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersistenceId")); b.Property("AttributeKey") .HasMaxLength(100) @@ -193,8 +200,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("PersistenceId") .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersistenceId")); b.Property("CommandName") .HasMaxLength(200) @@ -221,8 +229,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("PersistenceId") .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersistenceId")); b.Property("EventKey") .HasMaxLength(200) @@ -241,7 +250,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("character varying(200)"); b.Property("ExternalTokenExpiry") - .HasColumnType("timestamp without time zone"); + .HasColumnType("timestamp with time zone"); b.Property("ExternalWorkerId") .HasMaxLength(200) @@ -251,7 +260,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("integer"); b.Property("SubscribeAsOf") - .HasColumnType("timestamp without time zone"); + .HasColumnType("timestamp with time zone"); b.Property("SubscriptionData") .HasColumnType("text"); @@ -280,14 +289,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("PersistenceId") .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PersistenceId")); b.Property("CompleteTime") - .HasColumnType("timestamp without time zone"); + .HasColumnType("timestamp with time zone"); b.Property("CreateTime") - .HasColumnType("timestamp without time zone"); + .HasColumnType("timestamp with time zone"); b.Property("Data") .HasColumnType("text"); diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContext.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContext.cs index 3eb80b448..e9a371d7f 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContext.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/PostgresContext.cs @@ -66,6 +66,54 @@ protected override void ConfigureScheduledCommandStorage(EntityTypeBuilder x.PersistenceId).ValueGeneratedOnAdd(); } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.Entity(x => + { + x.Property(p => p.CompleteTime) + .HasColumnType("timestamp with time zone"); + + x.Property(p => p.CreateTime) + .HasColumnType("timestamp with time zone"); + }); + + modelBuilder.Entity(x => + { + x.Property(p => p.SleepUntil) + .HasColumnType("timestamp with time zone"); + + x.Property(p => p.StartTime) + .HasColumnType("timestamp with time zone"); + + x.Property(p => p.EndTime) + .HasColumnType("timestamp with time zone"); + + }); + + modelBuilder.Entity(x => + { + x.Property(p => p.ErrorTime) + .HasColumnType("timestamp with time zone"); + + }); + + modelBuilder.Entity(x => + { + x.Property(p => p.SubscribeAsOf) + .HasColumnType("timestamp with time zone"); + + x.Property(p => p.ExternalTokenExpiry) + .HasColumnType("timestamp with time zone"); + }); + + modelBuilder.Entity( + x => x.Property(x => x.EventTime) + .HasColumnType("timestamp with time zone") + ); + } } } From b1e19fd2980976c8cd403705cc694ed7f4708ada Mon Sep 17 00:00:00 2001 From: yi_Xu Date: Sat, 9 Aug 2025 08:41:47 +0800 Subject: [PATCH 315/342] fix: fix DateTime typo --- ...0250807084543_ChangeDateTimeTypeForPostgreSQL.Designer.cs} | 4 ++-- ...L.cs => 20250807084543_ChangeDateTimeTypeForPostgreSQL.cs} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/{20250807084543_ChangeDataTimeTypeForPostgreSQL.Designer.cs => 20250807084543_ChangeDateTimeTypeForPostgreSQL.Designer.cs} (99%) rename src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/{20250807084543_ChangeDataTimeTypeForPostgreSQL.cs => 20250807084543_ChangeDateTimeTypeForPostgreSQL.cs} (99%) diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDataTimeTypeForPostgreSQL.Designer.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDateTimeTypeForPostgreSQL.Designer.cs similarity index 99% rename from src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDataTimeTypeForPostgreSQL.Designer.cs rename to src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDateTimeTypeForPostgreSQL.Designer.cs index 407a461da..63e6094bb 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDataTimeTypeForPostgreSQL.Designer.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDateTimeTypeForPostgreSQL.Designer.cs @@ -12,8 +12,8 @@ namespace WorkflowCore.Persistence.PostgreSQL.Migrations { [DbContext(typeof(PostgresContext))] - [Migration("20250807084543_ChangeDataTimeTypeForPostgreSQL")] - partial class ChangeDataTimeTypeForPostgreSQL + [Migration("20250807084543_ChangeDateTimeTypeForPostgreSQL")] + partial class ChangeDateTimeTypeForPostgreSQL { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDataTimeTypeForPostgreSQL.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDateTimeTypeForPostgreSQL.cs similarity index 99% rename from src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDataTimeTypeForPostgreSQL.cs rename to src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDateTimeTypeForPostgreSQL.cs index 1e892fc44..42ebf73dc 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDataTimeTypeForPostgreSQL.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/20250807084543_ChangeDateTimeTypeForPostgreSQL.cs @@ -6,7 +6,7 @@ namespace WorkflowCore.Persistence.PostgreSQL.Migrations { /// - public partial class ChangeDataTimeTypeForPostgreSQL : Migration + public partial class ChangeDateTimeTypeForPostgreSQL : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) From b78a79f5f6e53cdf9b9a8bc53d2a9de0f33c0d47 Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Thu, 14 Aug 2025 08:43:40 -0700 Subject: [PATCH 316/342] Update Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 061235f4f..0f61a837a 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.14.0 - 3.14.0.0 - 3.14.0.0 + 3.15.0 + 3.15.0.0 + 3.15.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.14.0 + 3.15.0 From 00d0a6afa8ddccedbe14fb06aaefde888a7009c1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Sep 2025 16:58:30 +0000 Subject: [PATCH 317/342] Initial plan From 39f8d02aa23e7eb842f35354cc024f0a451f404f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Sep 2025 16:58:51 +0000 Subject: [PATCH 318/342] Initial plan From 57259d15a1639036902b0ccd4d0c7d6861b316d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Sep 2025 16:59:17 +0000 Subject: [PATCH 319/342] Initial plan From ebe9db180e6a5b2812cede5e01e28792e2be26b1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Sep 2025 17:07:42 +0000 Subject: [PATCH 320/342] Add .NET 8.0 support to MySQL persistence provider to fix CoreTypeMappingParameters error Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../WorkflowCore.Persistence.MySQL.csproj | 10 +++++++++- .../WorkflowCore.Tests.MySQL.csproj | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index 8b87ba216..a7efa31f2 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -4,7 +4,7 @@ Workflow Core MySQL Persistence Provider 1.0.0 Daniel Gerlag - netstandard2.1;net6.0 + netstandard2.1;net6.0;net8.0 WorkflowCore.Persistence.MySQL WorkflowCore.Persistence.MySQL workflow;.NET;Core;state machine;WorkflowCore;MySQL @@ -42,6 +42,14 @@ + + + all + runtime; build; native; contentfiles; analyzers + + + + diff --git a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj index 4ee96725f..bdb4029e7 100644 --- a/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj +++ b/test/WorkflowCore.Tests.MySQL/WorkflowCore.Tests.MySQL.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 From df2f9f5349348e503fddce83344a63f723069bb6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Sep 2025 17:11:25 +0000 Subject: [PATCH 321/342] Update RabbitMQ.Client to v7.0.0 with full API migration Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../ServiceCollectionExtensions.cs | 8 ++-- .../Services/RabbitMQProvider.cs | 45 ++++++++++++------- ...orkflowCore.QueueProviders.RabbitMQ.csproj | 2 +- ...wCore.Tests.QueueProviders.RabbitMQ.csproj | 6 ++- 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/ServiceCollectionExtensions.cs b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/ServiceCollectionExtensions.cs index 4474e403a..33be17272 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/ServiceCollectionExtensions.cs +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/ServiceCollectionExtensions.cs @@ -2,6 +2,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection.Extensions; using WorkflowCore.Interface; using WorkflowCore.Models; @@ -10,7 +12,7 @@ namespace Microsoft.Extensions.DependencyInjection { - public delegate IConnection RabbitMqConnectionFactory(IServiceProvider sp, string clientProvidedName); + public delegate Task RabbitMqConnectionFactory(IServiceProvider sp, string clientProvidedName, CancellationToken cancellationToken = default); public static class ServiceCollectionExtensions { @@ -20,7 +22,7 @@ public static WorkflowOptions UseRabbitMQ(this WorkflowOptions options, IConnect if (connectionFactory == null) throw new ArgumentNullException(nameof(connectionFactory)); return options - .UseRabbitMQ((sp, name) => connectionFactory.CreateConnection(name)); + .UseRabbitMQ(async (sp, name, cancellationToken) => await connectionFactory.CreateConnectionAsync(name, cancellationToken)); } public static WorkflowOptions UseRabbitMQ(this WorkflowOptions options, @@ -32,7 +34,7 @@ public static WorkflowOptions UseRabbitMQ(this WorkflowOptions options, if (hostnames == null) throw new ArgumentNullException(nameof(hostnames)); return options - .UseRabbitMQ((sp, name) => connectionFactory.CreateConnection(hostnames.ToList(), name)); + .UseRabbitMQ(async (sp, name, cancellationToken) => await connectionFactory.CreateConnectionAsync(hostnames, name, cancellationToken)); } public static WorkflowOptions UseRabbitMQ(this WorkflowOptions options, RabbitMqConnectionFactory rabbitMqConnectionFactory) diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs index 8a4ab33bb..1554d8bed 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/Services/RabbitMQProvider.cs @@ -37,11 +37,16 @@ public async Task QueueWork(string id, QueueType queue) if (_connection == null) throw new InvalidOperationException("RabbitMQ provider not running"); - using (var channel = _connection.CreateModel()) + var channel = await _connection.CreateChannelAsync(new CreateChannelOptions(publisherConfirmationsEnabled: false, publisherConfirmationTrackingEnabled: false), CancellationToken.None); + try { - channel.QueueDeclare(queue: _queueNameProvider.GetQueueName(queue), durable: true, exclusive: false, autoDelete: false, arguments: null); - var body = Encoding.UTF8.GetBytes(id); - channel.BasicPublish(exchange: "", routingKey: _queueNameProvider.GetQueueName(queue), basicProperties: null, body: body); + await channel.QueueDeclareAsync(queue: _queueNameProvider.GetQueueName(queue), durable: true, exclusive: false, autoDelete: false, arguments: null, passive: false, noWait: false, CancellationToken.None); + var body = new ReadOnlyMemory(Encoding.UTF8.GetBytes(id)); + await channel.BasicPublishAsync(exchange: "", routingKey: _queueNameProvider.GetQueueName(queue), mandatory: false, basicProperties: new BasicProperties(), body: body, CancellationToken.None); + } + finally + { + await channel.CloseAsync(200, "OK", abort: false, CancellationToken.None); } } @@ -50,25 +55,33 @@ public async Task DequeueWork(QueueType queue, CancellationToken cancell if (_connection == null) throw new InvalidOperationException("RabbitMQ provider not running"); - using (var channel = _connection.CreateModel()) + var channel = await _connection.CreateChannelAsync(new CreateChannelOptions(publisherConfirmationsEnabled: false, publisherConfirmationTrackingEnabled: false), CancellationToken.None); + try { - channel.QueueDeclare(queue: _queueNameProvider.GetQueueName(queue), - durable: true, - exclusive: false, - autoDelete: false, - arguments: null); + await channel.QueueDeclareAsync(queue: _queueNameProvider.GetQueueName(queue), + durable: true, + exclusive: false, + autoDelete: false, + arguments: null, + passive: false, + noWait: false, + CancellationToken.None); - channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false); + await channel.BasicQosAsync(prefetchSize: 0, prefetchCount: 1, global: false, CancellationToken.None); - var msg = channel.BasicGet(_queueNameProvider.GetQueueName(queue), false); + var msg = await channel.BasicGetAsync(_queueNameProvider.GetQueueName(queue), autoAck: false, CancellationToken.None); if (msg != null) { var data = Encoding.UTF8.GetString(msg.Body.ToArray()); - channel.BasicAck(msg.DeliveryTag, false); + await channel.BasicAckAsync(msg.DeliveryTag, multiple: false, CancellationToken.None); return data; } return null; } + finally + { + await channel.CloseAsync(200, "OK", abort: false, CancellationToken.None); + } } public void Dispose() @@ -76,20 +89,20 @@ public void Dispose() if (_connection != null) { if (_connection.IsOpen) - _connection.Close(); + _connection.CloseAsync(200, "OK", TimeSpan.FromSeconds(10), abort: false, CancellationToken.None).GetAwaiter().GetResult(); } } public async Task Start() { - _connection = _rabbitMqConnectionFactory(_serviceProvider, "Workflow-Core"); + _connection = await _rabbitMqConnectionFactory(_serviceProvider, "Workflow-Core"); } public async Task Stop() { if (_connection != null) { - _connection.Close(); + await _connection.CloseAsync(200, "OK", TimeSpan.FromSeconds(10), abort: false, CancellationToken.None); _connection = null; } } diff --git a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj index df02daa76..4729c7eeb 100644 --- a/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj +++ b/src/providers/WorkflowCore.QueueProviders.RabbitMQ/WorkflowCore.QueueProviders.RabbitMQ.csproj @@ -23,7 +23,7 @@ - + diff --git a/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj b/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj index 5fc77518a..f8489e483 100644 --- a/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj +++ b/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj @@ -1,11 +1,15 @@ - net6.0 + net8.0 + + + + From f7e3dd97283bdf4d037ecbe08327fcfe4d0dd9b9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Sep 2025 17:12:44 +0000 Subject: [PATCH 322/342] Fix workflow consumer greylist removal to prevent stuck workflows Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../BackgroundTasks/WorkflowConsumer.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs index ad9c9e6f6..c7d13138b 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/WorkflowConsumer.cs @@ -8,6 +8,11 @@ namespace WorkflowCore.Services.BackgroundTasks { + /// + /// Background task responsible for consuming workflow items from the queue and processing them. + /// This consumer ensures that workflows are removed from the greylist after processing, + /// regardless of their status, to prevent workflows from getting stuck in "Pending" state. + /// internal class WorkflowConsumer : QueueConsumer, IBackgroundTask { private readonly IDistributedLockProvider _lockProvider; @@ -57,12 +62,25 @@ protected override async Task ProcessItem(string itemId, CancellationToken cance WorkflowActivity.Enrich(result); await _persistenceStore.PersistWorkflow(workflow, result?.Subscriptions, cancellationToken); await QueueProvider.QueueWork(itemId, QueueType.Index); - _greylist.Remove($"wf:{itemId}"); } } + else + { + Logger.LogDebug("Workflow {ItemId} is not runnable, status: {Status}", itemId, workflow.Status); + } + } + catch (Exception ex) + { + Logger.LogError(ex, "Error processing workflow {ItemId}", itemId); + throw; } finally { + // Always remove from greylist regardless of workflow status + // This prevents workflows from being stuck in greylist when they can't be processed + Logger.LogDebug("Removing workflow {ItemId} from greylist", itemId); + _greylist.Remove($"wf:{itemId}"); + await _lockProvider.ReleaseLock(itemId); if ((workflow != null) && (result != null)) { From 7f96f677b4392efc3115b6753b759566c911d0e6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 8 Sep 2025 17:14:57 +0000 Subject: [PATCH 323/342] Clean up test project file to remove duplicate package warnings Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj b/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj index f8489e483..40ba780ac 100644 --- a/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj +++ b/test/WorkflowCore.Tests.QueueProviders.RabbitMQ/WorkflowCore.Tests.QueueProviders.RabbitMQ.csproj @@ -6,10 +6,6 @@ - - - - From 5acbc1e5f3e68f44400b4e09e0e8e69b599fde0d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Sep 2025 22:59:31 +0000 Subject: [PATCH 324/342] Initial plan From 3a34dd9139f488eb65ee2b5588ae6bb00ad6e65e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Sep 2025 23:03:13 +0000 Subject: [PATCH 325/342] Initial analysis: Updated OpenTelemetry.Api to 1.12.0 and identified breaking changes Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- src/WorkflowCore/WorkflowCore.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WorkflowCore/WorkflowCore.csproj b/src/WorkflowCore/WorkflowCore.csproj index bb567d87c..ab0607213 100644 --- a/src/WorkflowCore/WorkflowCore.csproj +++ b/src/WorkflowCore/WorkflowCore.csproj @@ -26,8 +26,8 @@ - - + + <_Parameter1>WorkflowCore.IntegrationTests From ea9169117ee4e696c37fa493258fe445eb11a691 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Sep 2025 23:04:59 +0000 Subject: [PATCH 326/342] Initial plan From fce2fc768f9b8db553ac5386a971b9648f22a2d7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Sep 2025 23:10:30 +0000 Subject: [PATCH 327/342] Complete OpenTelemetry update: Fixed all breaking API changes for version 1.12.0 Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../Services/BackgroundTasks/QueueConsumer.cs | 4 ++-- .../Services/BackgroundTasks/RunnablePoller.cs | 10 +++++----- src/WorkflowCore/Services/WorkflowActivity.cs | 1 - src/WorkflowCore/Services/WorkflowHost.cs | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs b/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs index a5392ecbb..75a7583ad 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/QueueConsumer.cs @@ -122,7 +122,7 @@ private async Task Execute() catch (Exception ex) { Logger.LogError(ex, ex.Message); - activity?.RecordException(ex); + activity?.AddException(ex); } finally { @@ -158,7 +158,7 @@ private async Task ExecuteItem(string itemId, EventWaitHandle waitHandle, Activi catch (Exception ex) { Logger.LogError(default(EventId), ex, $"Error executing item {itemId} - {ex.Message}"); - activity?.RecordException(ex); + activity?.AddException(ex); } finally { diff --git a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs index 29b76837c..fc7c0887f 100644 --- a/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs +++ b/src/WorkflowCore/Services/BackgroundTasks/RunnablePoller.cs @@ -86,7 +86,7 @@ await _persistenceStore.ScheduleCommand(new ScheduledCommand() catch (Exception ex) { _logger.LogError(ex, ex.Message); - activity?.RecordException(ex); + activity?.AddException(ex); } } if (_greylist.Contains($"wf:{item}")) @@ -108,7 +108,7 @@ await _persistenceStore.ScheduleCommand(new ScheduledCommand() catch (Exception ex) { _logger.LogError(ex, ex.Message); - activity?.RecordException(ex); + activity?.AddException(ex); } finally { @@ -145,7 +145,7 @@ await _persistenceStore.ScheduleCommand(new ScheduledCommand() catch (Exception ex) { _logger.LogError(ex, ex.Message); - activity?.RecordException(ex); + activity?.AddException(ex); } } if (_greylist.Contains($"evt:{item}")) @@ -167,7 +167,7 @@ await _persistenceStore.ScheduleCommand(new ScheduledCommand() catch (Exception ex) { _logger.LogError(ex, ex.Message); - activity?.RecordException(ex); + activity?.AddException(ex); } finally { @@ -210,7 +210,7 @@ await _persistenceStore.ProcessCommands(new DateTimeOffset(_dateTimeProvider.Utc catch (Exception ex) { _logger.LogError(ex, ex.Message); - activity?.RecordException(ex); + activity?.AddException(ex); } finally { diff --git a/src/WorkflowCore/Services/WorkflowActivity.cs b/src/WorkflowCore/Services/WorkflowActivity.cs index 80c719fb8..3fe3b720c 100644 --- a/src/WorkflowCore/Services/WorkflowActivity.cs +++ b/src/WorkflowCore/Services/WorkflowActivity.cs @@ -83,7 +83,6 @@ internal static void Enrich(WorkflowExecutorResult result) if (result?.Errors?.Count > 0) { - activity.SetStatus(Status.Error); activity.SetStatus(ActivityStatusCode.Error); } } diff --git a/src/WorkflowCore/Services/WorkflowHost.cs b/src/WorkflowCore/Services/WorkflowHost.cs index 73c8850fa..d2a09ec70 100644 --- a/src/WorkflowCore/Services/WorkflowHost.cs +++ b/src/WorkflowCore/Services/WorkflowHost.cs @@ -105,7 +105,7 @@ public async Task StartAsync(CancellationToken cancellationToken) } catch (Exception ex) { - activity.RecordException(ex); + activity.AddException(ex); throw; } finally From b375bd22696cfce6023f041e83a753417b066a0b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Sep 2025 23:13:26 +0000 Subject: [PATCH 328/342] Update Entity Framework dependencies from 8.* to 9.* for net8.0 builds Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../WorkflowCore.Persistence.EntityFramework.csproj | 2 +- .../WorkflowCore.Persistence.Oracle.csproj | 6 +++--- .../WorkflowCore.Persistence.PostgreSQL.csproj | 8 ++++---- .../WorkflowCore.Persistence.SqlServer.csproj | 6 +++--- .../WorkflowCore.Persistence.Sqlite.csproj | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj index f161d1299..8351a579e 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/WorkflowCore.Persistence.EntityFramework.csproj @@ -26,7 +26,7 @@ - + diff --git a/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj b/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj index e49e1a88a..138ec3b95 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj +++ b/src/providers/WorkflowCore.Persistence.Oracle/WorkflowCore.Persistence.Oracle.csproj @@ -19,14 +19,14 @@ - + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj index be939451b..b79511625 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/WorkflowCore.Persistence.PostgreSQL.csproj @@ -35,12 +35,12 @@ - - - + + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj index 2c4f5cee3..f617bfa05 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj +++ b/src/providers/WorkflowCore.Persistence.SqlServer/WorkflowCore.Persistence.SqlServer.csproj @@ -35,11 +35,11 @@ - - + + All - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj index 1797e054b..d1fc08d7c 100644 --- a/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj +++ b/src/providers/WorkflowCore.Persistence.Sqlite/WorkflowCore.Persistence.Sqlite.csproj @@ -28,7 +28,7 @@ - + From 21e562901ccbff5fe6cb2037ec8775d2600fdd5e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Sep 2025 16:49:34 +0000 Subject: [PATCH 329/342] Add MySQL provider support for .NET 8.0 with Entity Framework 9 Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../WorkflowCore.Persistence.MySQL.csproj | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj index 8b87ba216..c0fc07851 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj +++ b/src/providers/WorkflowCore.Persistence.MySQL/WorkflowCore.Persistence.MySQL.csproj @@ -4,7 +4,7 @@ Workflow Core MySQL Persistence Provider 1.0.0 Daniel Gerlag - netstandard2.1;net6.0 + netstandard2.1;net6.0;net8.0 WorkflowCore.Persistence.MySQL WorkflowCore.Persistence.MySQL workflow;.NET;Core;state machine;WorkflowCore;MySQL @@ -42,6 +42,14 @@ + + + all + runtime; build; native; contentfiles; analyzers + + + + From 4cb79354e34ea5f187e14370897494541ed4a0fc Mon Sep 17 00:00:00 2001 From: Daniel Gerlag Date: Wed, 17 Sep 2025 14:25:26 -0700 Subject: [PATCH 330/342] Bump version to 3.16.0 in Directory.Build.props --- src/Directory.Build.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 0f61a837a..219e6f838 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,10 +4,10 @@ https://github.com/danielgerlag/workflow-core/blob/master/LICENSE.md git https://github.com/danielgerlag/workflow-core.git - 3.15.0 - 3.15.0.0 - 3.15.0.0 + 3.16.0 + 3.16.0.0 + 3.16.0.0 https://github.com/danielgerlag/workflow-core/raw/master/src/logo.png - 3.15.0 + 3.16.0 From 930061476f17def76927fd125c640c0d4bbf9446 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Sep 2025 00:35:55 +0000 Subject: [PATCH 331/342] Initial plan From 248717c1460c45cf6b3925b44e526acd878c0573 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Sep 2025 00:45:10 +0000 Subject: [PATCH 332/342] Initial plan From 2ee1c52a73a31c36d16e7bed1ea56fb7703b78e4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Sep 2025 00:51:56 +0000 Subject: [PATCH 333/342] Update PostgreSQL ModelSnapshot ProductVersion to fix pending changes warning with EF Core 9 Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../Migrations/PostgresPersistenceProviderModelSnapshot.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs index 0783459b6..8fe59f5cd 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.19") + .HasAnnotation("ProductVersion", "9.0.9") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); From a61d0c43f510393fab77d633ffcaa05a8c66186c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Sep 2025 00:53:35 +0000 Subject: [PATCH 334/342] Upgrade System.Linq.Dynamic.Core to 1.6.0 and fix breaking changes Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../Services/DefinitionLoader.cs | 45 ++++++++++++++++--- src/WorkflowCore.DSL/WorkflowCore.DSL.csproj | 2 +- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs index c5cc5e083..aa22988eb 100644 --- a/src/WorkflowCore.DSL/Services/DefinitionLoader.cs +++ b/src/WorkflowCore.DSL/Services/DefinitionLoader.cs @@ -5,6 +5,7 @@ using System.Linq.Dynamic.Core; using System.Linq.Expressions; using System.Reflection; +using System.Text.RegularExpressions; using Newtonsoft.Json.Linq; using WorkflowCore.Interface; using WorkflowCore.Models; @@ -18,6 +19,40 @@ public class DefinitionLoader : IDefinitionLoader { private readonly IWorkflowRegistry _registry; private readonly ITypeResolver _typeResolver; + + // ParsingConfig to allow access to commonly used .NET methods like object.Equals + private static readonly ParsingConfig ParsingConfig = new ParsingConfig + { + AllowNewToEvaluateAnyType = true, + AreContextKeywordsEnabled = true + }; + + // Transform expressions to be compatible with System.Linq.Dynamic.Core 1.6.0+ + private static string TransformExpression(string expression) + { + if (string.IsNullOrEmpty(expression)) + return expression; + + // Transform object.Equals(a, b) to Convert.ToBoolean(a) == Convert.ToBoolean(b) + // This is a simple regex replacement for the common pattern + var objectEqualsPattern = @"object\.Equals\s*\(\s*([^,]+)\s*,\s*([^)]+)\s*\)"; + var transformed = Regex.Replace(expression, objectEqualsPattern, + match => + { + var arg1 = match.Groups[1].Value.Trim(); + var arg2 = match.Groups[2].Value.Trim(); + + // If arg2 is a boolean literal, convert arg1 to boolean and compare + if (arg2 == "true" || arg2 == "false") + { + return $"Convert.ToBoolean({arg1}) == {arg2}"; + } + // Otherwise, convert both to strings for comparison + return $"Convert.ToString({arg1}) == Convert.ToString({arg2})"; + }); + + return transformed; + } public DefinitionLoader(IWorkflowRegistry registry, ITypeResolver typeResolver) { @@ -94,7 +129,7 @@ private WorkflowStepCollection ConvertSteps(ICollection source, Ty { var cancelExprType = typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(dataType, typeof(bool))); var dataParameter = Expression.Parameter(dataType, "data"); - var cancelExpr = DynamicExpressionParser.ParseLambda(new[] { dataParameter }, typeof(bool), nextStep.CancelCondition); + var cancelExpr = DynamicExpressionParser.ParseLambda(ParsingConfig, false, new[] { dataParameter }, typeof(bool), TransformExpression(nextStep.CancelCondition)); targetStep.CancelCondition = cancelExpr; } @@ -217,7 +252,7 @@ private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, Wo foreach (var output in source.Outputs) { var stepParameter = Expression.Parameter(stepType, "step"); - var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { stepParameter }, typeof(object), output.Value); + var sourceExpr = DynamicExpressionParser.ParseLambda(ParsingConfig, false, new[] { stepParameter }, typeof(object), TransformExpression(output.Value)); var dataParameter = Expression.Parameter(dataType, "data"); @@ -344,7 +379,7 @@ private void AttachOutcomes(StepSourceV1 source, Type dataType, WorkflowStep ste foreach (var nextStep in source.SelectNextStep) { - var sourceDelegate = DynamicExpressionParser.ParseLambda(new[] { dataParameter, outcomeParameter }, typeof(object), nextStep.Value).Compile(); + var sourceDelegate = DynamicExpressionParser.ParseLambda(ParsingConfig, false, new[] { dataParameter, outcomeParameter }, typeof(object), TransformExpression(nextStep.Value)).Compile(); Expression> sourceExpr = (data, outcome) => System.Convert.ToBoolean(sourceDelegate.DynamicInvoke(data, outcome)); step.Outcomes.Add(new ExpressionOutcome(sourceExpr) { @@ -361,7 +396,7 @@ private Type FindType(string name) private static Action BuildScalarInputAction(KeyValuePair input, ParameterExpression dataParameter, ParameterExpression contextParameter, ParameterExpression environmentVarsParameter, PropertyInfo stepProperty) { var expr = System.Convert.ToString(input.Value); - var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { dataParameter, contextParameter, environmentVarsParameter }, typeof(object), expr); + var sourceExpr = DynamicExpressionParser.ParseLambda(ParsingConfig, false, new[] { dataParameter, contextParameter, environmentVarsParameter }, typeof(object), TransformExpression(expr)); void acn(IStepBody pStep, object pData, IStepExecutionContext pContext) { @@ -394,7 +429,7 @@ void acn(IStepBody pStep, object pData, IStepExecutionContext pContext) { if (prop.Name.StartsWith("@")) { - var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { dataParameter, contextParameter, environmentVarsParameter }, typeof(object), prop.Value.ToString()); + var sourceExpr = DynamicExpressionParser.ParseLambda(ParsingConfig, false, new[] { dataParameter, contextParameter, environmentVarsParameter }, typeof(object), TransformExpression(prop.Value.ToString())); object resolvedValue = sourceExpr.Compile().DynamicInvoke(pData, pContext, Environment.GetEnvironmentVariables()); subobj.Remove(prop.Name); subobj.Add(prop.Name.TrimStart('@'), JToken.FromObject(resolvedValue)); diff --git a/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj b/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj index 94765a53e..9385da3d0 100644 --- a/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj +++ b/src/WorkflowCore.DSL/WorkflowCore.DSL.csproj @@ -11,7 +11,7 @@ - + From c8fb30ce5e4849d2a22107444207087d06afd8e8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Sep 2025 00:58:01 +0000 Subject: [PATCH 335/342] Fix ProductVersion in all EF Core persistence providers to prevent pending changes warning with EF Core 9 Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../Migrations/MysqlPersistenceProviderModelSnapshot.cs | 2 +- .../Migrations/OracleContextModelSnapshot.cs | 2 +- .../Migrations/SqlServerPersistenceProviderModelSnapshot.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs index 8a3e02e9b..ab55c6b69 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs @@ -15,7 +15,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasAnnotation("Relational:MaxIdentifierLength", 64) - .HasAnnotation("ProductVersion", "5.0.8"); + .HasAnnotation("ProductVersion", "9.0.9"); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => { diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs index 6d600dcc5..d8e0e3dda 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "6.0.3") + .HasAnnotation("ProductVersion", "9.0.9") .HasAnnotation("Relational:MaxIdentifierLength", 128); OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs index 39da38276..d0f0a6650 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs @@ -16,7 +16,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.8") + .HasAnnotation("ProductVersion", "9.0.9") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => From cb41852d44fe7542bc2e2e2e9e6b529764b9ab3f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Sep 2025 05:22:34 +0000 Subject: [PATCH 336/342] Fix ProductVersion compatibility by suppressing pending model changes warning instead of updating ModelSnapshots Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../Services/WorkflowDbContext.cs | 5 +++++ .../Migrations/MysqlPersistenceProviderModelSnapshot.cs | 2 +- .../Migrations/OracleContextModelSnapshot.cs | 2 +- .../Migrations/PostgresPersistenceProviderModelSnapshot.cs | 2 +- .../Migrations/SqlServerPersistenceProviderModelSnapshot.cs | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs index 53e0967e7..427447416 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs @@ -56,6 +56,11 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); + + // Suppress pending model changes warning when using newer EF Core versions with older ModelSnapshots + // This prevents false positive warnings when the ProductVersion in ModelSnapshot differs from runtime + optionsBuilder.ConfigureWarnings(warnings => + warnings.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning)); } } } diff --git a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs index ab55c6b69..8a3e02e9b 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs @@ -15,7 +15,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasAnnotation("Relational:MaxIdentifierLength", 64) - .HasAnnotation("ProductVersion", "9.0.9"); + .HasAnnotation("ProductVersion", "5.0.8"); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => { diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs index d8e0e3dda..6d600dcc5 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "9.0.9") + .HasAnnotation("ProductVersion", "6.0.3") .HasAnnotation("Relational:MaxIdentifierLength", 128); OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs index 8fe59f5cd..0783459b6 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "9.0.9") + .HasAnnotation("ProductVersion", "8.0.19") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs index d0f0a6650..39da38276 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs @@ -16,7 +16,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "9.0.9") + .HasAnnotation("ProductVersion", "5.0.8") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => From bf8a65ab644d98012881f6e09014e9c2377c4241 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 00:29:43 +0000 Subject: [PATCH 337/342] Initial plan From 82932f7423206ba7181f8969d25cb911edb979de Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 00:32:03 +0000 Subject: [PATCH 338/342] Improve warning handling by logging instead of ignoring PendingModelChangesWarning Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../Services/WorkflowDbContext.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs index 427447416..7661f4111 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs @@ -57,10 +57,15 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) base.OnConfiguring(optionsBuilder); optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); - // Suppress pending model changes warning when using newer EF Core versions with older ModelSnapshots - // This prevents false positive warnings when the ProductVersion in ModelSnapshot differs from runtime + // Configure warning handling for PendingModelChangesWarning + // This warning can be triggered by: + // 1. ProductVersion mismatch (false positive when using EF Core 9.x with older snapshots) + // 2. Legitimate model changes that need migrations + // + // We convert the warning to a log message so developers can still see it in logs + // but it won't throw an exception that prevents application startup optionsBuilder.ConfigureWarnings(warnings => - warnings.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning)); + warnings.Log(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning)); } } } From 2d367049dceb7c3f275d28566c52884e75761ffc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 00:34:08 +0000 Subject: [PATCH 339/342] Initial plan From 13860f28b88abb906a4848e458018fb84db34147 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 00:39:29 +0000 Subject: [PATCH 340/342] Add documentation for Sample08 human workflow Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- README.md | 4 +- src/samples/WorkflowCore.Sample08/README.md | 71 +++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 src/samples/WorkflowCore.Sample08/README.md diff --git a/README.md b/README.md index 0429fb597..ab398cc2c 100644 --- a/README.md +++ b/README.md @@ -185,12 +185,12 @@ These are also available as separate Nuget packages. * [Deferred execution & re-entrant steps](src/samples/WorkflowCore.Sample05) +* [Human(User) Workflow](src/samples/WorkflowCore.Sample08) + * [Looping](src/samples/WorkflowCore.Sample02) * [Exposing a REST API](src/samples/WebApiSample) -* [Human(User) Workflow](src/samples/WorkflowCore.Sample08) - * [Testing](src/samples/WorkflowCore.TestSample01) diff --git a/src/samples/WorkflowCore.Sample08/README.md b/src/samples/WorkflowCore.Sample08/README.md new file mode 100644 index 000000000..7c6e83c51 --- /dev/null +++ b/src/samples/WorkflowCore.Sample08/README.md @@ -0,0 +1,71 @@ +# Human (User) Workflow Sample + +This sample demonstrates how to create workflows that require human interaction using the WorkflowCore.Users extension. + +## What this sample shows + +* **User Tasks**: How to create tasks that are assigned to specific users or groups +* **User Options**: How to provide multiple choice options for users to select from +* **Conditional Branching**: How to execute different workflow paths based on user choices +* **Task Escalation**: How to automatically reassign tasks to different users when timeouts occur +* **User Action Management**: How to retrieve open user actions and publish user responses programmatically + +## The Workflow + +```c# +public class HumanWorkflow : IWorkflow +{ + public void Build(IWorkflowBuilder builder) + { + builder + .StartWith(context => ExecutionResult.Next()) + .UserTask("Do you approve", data => @"domain\bob") + .WithOption("yes", "I approve").Do(then => then + .StartWith(context => Console.WriteLine("You approved")) + ) + .WithOption("no", "I do not approve").Do(then => then + .StartWith(context => Console.WriteLine("You did not approve")) + ) + .WithEscalation(x => TimeSpan.FromSeconds(20), x => @"domain\frank", action => action + .StartWith(context => Console.WriteLine("Escalated task")) + .Then(context => Console.WriteLine("Sending notification...")) + ) + .Then(context => Console.WriteLine("end")); + } +} +``` + +## How it works + +1. **Task Assignment**: The workflow creates a user task with the prompt "Do you approve" and assigns it to `domain\bob` + +2. **User Options**: Two options are provided: + - "yes" with label "I approve" - executes approval workflow + - "no" with label "I do not approve" - executes rejection workflow + +3. **Escalation**: If the task is not completed within 20 seconds, it automatically escalates to `domain\frank` and executes the escalation workflow + +4. **User Interaction**: The program demonstrates how to: + - Get open user actions using `host.GetOpenUserActions(workflowId)` + - Display options to the user + - Publish user responses using `host.PublishUserAction(key, user, value)` + +## Key Features + +* **UserTask**: Creates tasks that wait for human input +* **WithOption**: Defines multiple choice options with conditional workflow paths +* **WithEscalation**: Automatically reassigns tasks after a timeout period +* **Interactive Console**: Shows how to build a simple interface for user interaction + +## Dependencies + +This sample requires the `WorkflowCore.Users` extension package, which provides the human workflow capabilities. + +## Use Cases + +This pattern is useful for: +- Approval workflows +- Decision-making processes +- Task assignment and escalation +- Interactive business processes +- Multi-step user interactions \ No newline at end of file From 4f05e9164e05c50ea43e59cd075287521e53d0bc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 00:41:50 +0000 Subject: [PATCH 341/342] Fix PostgreSQL DateTime issue in ActivityController Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- src/WorkflowCore/Services/ActivityController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WorkflowCore/Services/ActivityController.cs b/src/WorkflowCore/Services/ActivityController.cs index e37481521..491f9c47e 100644 --- a/src/WorkflowCore/Services/ActivityController.cs +++ b/src/WorkflowCore/Services/ActivityController.cs @@ -34,7 +34,7 @@ public async Task GetPendingActivity(string activityName, strin { if (!firstPass) await Task.Delay(100); - subscription = await _subscriptionRepository.GetFirstOpenSubscription(Event.EventTypeActivity, activityName, _dateTimeProvider.Now); + subscription = await _subscriptionRepository.GetFirstOpenSubscription(Event.EventTypeActivity, activityName, _dateTimeProvider.UtcNow); if (subscription != null) if (!await _lockProvider.AcquireLock($"sub:{subscription.Id}", CancellationToken.None)) subscription = null; @@ -51,7 +51,7 @@ public async Task GetPendingActivity(string activityName, strin Token = token.Encode(), ActivityName = subscription.EventKey, Parameters = subscription.SubscriptionData, - TokenExpiry = DateTime.MaxValue + TokenExpiry = new DateTime(DateTime.MaxValue.Ticks, DateTimeKind.Utc) }; if (!await _subscriptionRepository.SetSubscriptionToken(subscription.Id, result.Token, workerId, result.TokenExpiry)) From 216a1e32c96fae9536e6c6c4eb364bff3534b0d9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 16:26:20 +0000 Subject: [PATCH 342/342] Implement dynamic ProductVersion based on target framework using preprocessor directives Co-authored-by: danielgerlag <2357007+danielgerlag@users.noreply.github.com> --- .../Services/WorkflowDbContext.cs | 10 ---------- .../MysqlPersistenceProviderModelSnapshot.cs | 11 ++++++++++- .../Migrations/OracleContextModelSnapshot.cs | 8 +++++++- .../PostgresPersistenceProviderModelSnapshot.cs | 10 +++++++++- .../SqlServerPersistenceProviderModelSnapshot.cs | 10 +++++++++- 5 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs index 7661f4111..53e0967e7 100644 --- a/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs +++ b/src/providers/WorkflowCore.Persistence.EntityFramework/Services/WorkflowDbContext.cs @@ -56,16 +56,6 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); - - // Configure warning handling for PendingModelChangesWarning - // This warning can be triggered by: - // 1. ProductVersion mismatch (false positive when using EF Core 9.x with older snapshots) - // 2. Legitimate model changes that need migrations - // - // We convert the warning to a log message so developers can still see it in logs - // but it won't throw an exception that prevents application startup - optionsBuilder.ConfigureWarnings(warnings => - warnings.Log(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning)); } } } diff --git a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs index 8a3e02e9b..59d48fac7 100644 --- a/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.MySQL/Migrations/MysqlPersistenceProviderModelSnapshot.cs @@ -15,7 +15,16 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasAnnotation("Relational:MaxIdentifierLength", 64) - .HasAnnotation("ProductVersion", "5.0.8"); +#if NETSTANDARD2_1 + .HasAnnotation("ProductVersion", "5.0.1") +#elif NET6_0 + .HasAnnotation("ProductVersion", "7.0.0") +#elif NET8_0 + .HasAnnotation("ProductVersion", "9.0.9") +#else + .HasAnnotation("ProductVersion", "9.0.9") +#endif + ; modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b => { diff --git a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs index 6d600dcc5..7d88a0220 100644 --- a/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.Oracle/Migrations/OracleContextModelSnapshot.cs @@ -17,7 +17,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "6.0.3") +#if NET6_0 + .HasAnnotation("ProductVersion", "7.0.0") +#elif NET8_0 + .HasAnnotation("ProductVersion", "9.0.9") +#else + .HasAnnotation("ProductVersion", "9.0.9") +#endif .HasAnnotation("Relational:MaxIdentifierLength", 128); OracleModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); diff --git a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs index 0783459b6..5feae3a10 100644 --- a/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.PostgreSQL/Migrations/PostgresPersistenceProviderModelSnapshot.cs @@ -17,7 +17,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.19") +#if NETSTANDARD2_1 + .HasAnnotation("ProductVersion", "5.0.1") +#elif NET6_0 + .HasAnnotation("ProductVersion", "7.0.0") +#elif NET8_0 + .HasAnnotation("ProductVersion", "9.0.9") +#else + .HasAnnotation("ProductVersion", "9.0.9") +#endif .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); diff --git a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs index 39da38276..299cdb315 100644 --- a/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs +++ b/src/providers/WorkflowCore.Persistence.SqlServer/Migrations/SqlServerPersistenceProviderModelSnapshot.cs @@ -16,7 +16,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.8") +#if NETSTANDARD2_1 + .HasAnnotation("ProductVersion", "5.0.1") +#elif NET6_0 + .HasAnnotation("ProductVersion", "7.0.0") +#elif NET8_0 || NET9_0 + .HasAnnotation("ProductVersion", "9.0.9") +#else + .HasAnnotation("ProductVersion", "9.0.9") +#endif .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("WorkflowCore.Persistence.EntityFramework.Models.PersistedEvent", b =>