diff --git a/src/ConductorSharp.Client/ConductorConstants.cs b/src/ConductorSharp.Client/ConductorConstants.cs index 99536e10..1a1145ef 100644 --- a/src/ConductorSharp.Client/ConductorConstants.cs +++ b/src/ConductorSharp.Client/ConductorConstants.cs @@ -15,5 +15,6 @@ public static class ConductorConstants MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead, TypeNameHandling = TypeNameHandling.Auto }; + public static JsonSerializer DefinitionsSerializer { get; } = new() { NullValueHandling = NullValueHandling.Ignore }; } } diff --git a/src/ConductorSharp.Engine/Builders/DecisionTaskBuilder.cs b/src/ConductorSharp.Engine/Builders/DecisionTaskBuilder.cs index 14b17db7..e0154354 100644 --- a/src/ConductorSharp.Engine/Builders/DecisionTaskBuilder.cs +++ b/src/ConductorSharp.Engine/Builders/DecisionTaskBuilder.cs @@ -1,161 +1,164 @@ -using ConductorSharp.Client.Model.Common; -using ConductorSharp.Engine.Interface; -using ConductorSharp.Engine.Model; -using MediatR; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; - -namespace ConductorSharp.Engine.Builders -{ - public static class DecisionTaskExtensions - { - public static ITaskOptionsBuilder AddTask( - this WorkflowDefinitionBuilder builder, - Expression> taskSelector, - Expression> expression, - params (string, Action>)[] caseActions - ) where TWorkflow : ITypedWorkflow - { - var taskBbuilder = new DecisionTaskBuilder(taskSelector.Body, expression.Body); - - foreach (var funcase in caseActions) - { - taskBbuilder.AddCase(funcase.Item1); - funcase.Item2.Invoke(taskBbuilder); - } - - builder.Context.TaskBuilders.Add(taskBbuilder); - return taskBbuilder; - } - } - - public class DecisionTaskBuilder : BaseTaskBuilder where TWorkflow : ITypedWorkflow - { - private Dictionary> _caseDictionary = new(); - - private string _currentCaseName; - - public DecisionTaskBuilder(Expression taskExpression, Expression inputExpression) : base(taskExpression, inputExpression) { } - - public DecisionTaskBuilder AddCase(string caseName) - { - _currentCaseName = caseName; - - if (!_caseDictionary.ContainsKey(_currentCaseName)) - _caseDictionary.Add(caseName, new List()); - - return this; - } - - public DecisionTaskBuilder WithTask( - Expression>> referrence, - Expression> input - ) where F : IRequest - { - var builder = new SubWorkflowTaskBuilder(referrence.Body, input.Body); - _caseDictionary[_currentCaseName].Add(builder); - - return this; - } - - public DecisionTaskBuilder WithTask( - Expression>> taskSelector, - Expression> expression, - string script - ) where F : IRequest - { - var builder = new LambdaTaskBuilder(script, taskSelector.Body, expression.Body); - _caseDictionary[_currentCaseName].Add(builder); - - return this; - } - - public DecisionTaskBuilder WithTask( - Expression> taskSelector, - Expression> expression - ) - { - var builder = new DynamicForkJoinTaskBuilder(taskSelector.Body, expression.Body); - _caseDictionary[_currentCaseName].Add(builder); - - return this; - } - - public DecisionTaskBuilder WithTask( - Expression>> taskSelector, - Expression> expression, - AdditionalTaskParameters additionalParameters = null - ) where F : IRequest - { - var builder = new SimpleTaskBuilder(taskSelector.Body, expression.Body, additionalParameters); - _caseDictionary[_currentCaseName].Add(builder); - - return this; - } - - public DecisionTaskBuilder WithTask( - Expression> taskSelector, - Expression> expression - ) - { - var builder = new TerminateTaskBuilder(taskSelector.Body, expression.Body); - _caseDictionary[_currentCaseName].Add(builder); - - return this; - } - - public DecisionTaskBuilder WithTask( - Expression>> taskSelector, - Expression>> expression - ) where F : IRequest - { - var builder = new DynamicTaskBuilder(taskSelector.Body, expression.Body); - _caseDictionary[_currentCaseName].Add(builder); - - return this; - } - - public DecisionTaskBuilder WithTask( - Expression> taskSelector, - Expression> expression, - params (string, Action>)[] caseActions - ) - { - var builder = new DecisionTaskBuilder(taskSelector.Body, expression.Body); - - foreach (var funcase in caseActions) - { - builder.AddCase(funcase.Item1); - funcase.Item2.Invoke(builder); - } - - _caseDictionary[_currentCaseName].Add(builder); - - return this; - } - - public override WorkflowDefinition.Task[] Build() - { - var decisionTaskName = $"DECISION_{_taskRefferenceName}"; - - return new WorkflowDefinition.Task[] - { - new WorkflowDefinition.Task - { - Name = decisionTaskName, - TaskReferenceName = _taskRefferenceName, - InputParameters = _inputParameters, - Type = "DECISION", - CaseValueParam = "case_value_param", - DecisionCases = new Newtonsoft.Json.Linq.JObject - { - _caseDictionary.Select(a => new JProperty(a.Key, JArray.FromObject(a.Value.SelectMany(a => a.Build())))) - } - } - }; - } - } -} +using ConductorSharp.Client; +using ConductorSharp.Client.Model.Common; +using ConductorSharp.Engine.Interface; +using ConductorSharp.Engine.Model; +using MediatR; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; + +namespace ConductorSharp.Engine.Builders +{ + public static class DecisionTaskExtensions + { + public static ITaskOptionsBuilder AddTask( + this WorkflowDefinitionBuilder builder, + Expression> taskSelector, + Expression> expression, + params (string, Action>)[] caseActions + ) where TWorkflow : ITypedWorkflow + { + var taskBbuilder = new DecisionTaskBuilder(taskSelector.Body, expression.Body); + + foreach (var funcase in caseActions) + { + taskBbuilder.AddCase(funcase.Item1); + funcase.Item2.Invoke(taskBbuilder); + } + + builder.Context.TaskBuilders.Add(taskBbuilder); + return taskBbuilder; + } + } + + public class DecisionTaskBuilder : BaseTaskBuilder where TWorkflow : ITypedWorkflow + { + private Dictionary> _caseDictionary = new(); + + private string _currentCaseName; + + public DecisionTaskBuilder(Expression taskExpression, Expression inputExpression) : base(taskExpression, inputExpression) { } + + public DecisionTaskBuilder AddCase(string caseName) + { + _currentCaseName = caseName; + + if (!_caseDictionary.ContainsKey(_currentCaseName)) + _caseDictionary.Add(caseName, new List()); + + return this; + } + + public DecisionTaskBuilder WithTask( + Expression>> referrence, + Expression> input + ) where F : IRequest + { + var builder = new SubWorkflowTaskBuilder(referrence.Body, input.Body); + _caseDictionary[_currentCaseName].Add(builder); + + return this; + } + + public DecisionTaskBuilder WithTask( + Expression>> taskSelector, + Expression> expression, + string script + ) where F : IRequest + { + var builder = new LambdaTaskBuilder(script, taskSelector.Body, expression.Body); + _caseDictionary[_currentCaseName].Add(builder); + + return this; + } + + public DecisionTaskBuilder WithTask( + Expression> taskSelector, + Expression> expression + ) + { + var builder = new DynamicForkJoinTaskBuilder(taskSelector.Body, expression.Body); + _caseDictionary[_currentCaseName].Add(builder); + + return this; + } + + public DecisionTaskBuilder WithTask( + Expression>> taskSelector, + Expression> expression, + AdditionalTaskParameters additionalParameters = null + ) where F : IRequest + { + var builder = new SimpleTaskBuilder(taskSelector.Body, expression.Body, additionalParameters); + _caseDictionary[_currentCaseName].Add(builder); + + return this; + } + + public DecisionTaskBuilder WithTask( + Expression> taskSelector, + Expression> expression + ) + { + var builder = new TerminateTaskBuilder(taskSelector.Body, expression.Body); + _caseDictionary[_currentCaseName].Add(builder); + + return this; + } + + public DecisionTaskBuilder WithTask( + Expression>> taskSelector, + Expression>> expression + ) where F : IRequest + { + var builder = new DynamicTaskBuilder(taskSelector.Body, expression.Body); + _caseDictionary[_currentCaseName].Add(builder); + + return this; + } + + public DecisionTaskBuilder WithTask( + Expression> taskSelector, + Expression> expression, + params (string, Action>)[] caseActions + ) + { + var builder = new DecisionTaskBuilder(taskSelector.Body, expression.Body); + + foreach (var funcase in caseActions) + { + builder.AddCase(funcase.Item1); + funcase.Item2.Invoke(builder); + } + + _caseDictionary[_currentCaseName].Add(builder); + + return this; + } + + public override WorkflowDefinition.Task[] Build() + { + var decisionTaskName = $"DECISION_{_taskRefferenceName}"; + + return new WorkflowDefinition.Task[] + { + new WorkflowDefinition.Task + { + Name = decisionTaskName, + TaskReferenceName = _taskRefferenceName, + InputParameters = _inputParameters, + Type = "DECISION", + CaseValueParam = "case_value_param", + DecisionCases = new Newtonsoft.Json.Linq.JObject + { + _caseDictionary.Select( + a => new JProperty(a.Key, JArray.FromObject(a.Value.SelectMany(a => a.Build()), ConductorConstants.DefinitionsSerializer)) + ) + } + } + }; + } + } +} diff --git a/src/ConductorSharp.Engine/Builders/SwitchTaskBuilder.cs b/src/ConductorSharp.Engine/Builders/SwitchTaskBuilder.cs index 2b039538..8c344685 100644 --- a/src/ConductorSharp.Engine/Builders/SwitchTaskBuilder.cs +++ b/src/ConductorSharp.Engine/Builders/SwitchTaskBuilder.cs @@ -1,4 +1,5 @@ -using ConductorSharp.Client.Model.Common; +using ConductorSharp.Client; +using ConductorSharp.Client.Model.Common; using ConductorSharp.Engine.Interface; using ConductorSharp.Engine.Model; using MediatR; @@ -152,7 +153,9 @@ public override WorkflowDefinition.Task[] Build() EvaluatorType = "value-param", DecisionCases = new Newtonsoft.Json.Linq.JObject { - _caseDictionary.Select(a => new JProperty(a.Key, JArray.FromObject(a.Value.SelectMany(b => b.Build())))) + _caseDictionary.Select( + a => new JProperty(a.Key, JArray.FromObject(a.Value.SelectMany(b => b.Build()), ConductorConstants.DefinitionsSerializer)) + ) } } }; diff --git a/test/ConductorSharp.Engine.Tests/Samples/Workflows/ConditionallySendCustomerNotificationOutput.json b/test/ConductorSharp.Engine.Tests/Samples/Workflows/ConditionallySendCustomerNotificationOutput.json index 0724c90b..4d9695e8 100644 --- a/test/ConductorSharp.Engine.Tests/Samples/Workflows/ConditionallySendCustomerNotificationOutput.json +++ b/test/ConductorSharp.Engine.Tests/Samples/Workflows/ConditionallySendCustomerNotificationOutput.json @@ -26,7 +26,6 @@ "decisionCases": { "YES": [ { - "queryExpression": null, "name": "NOTIFICATION_send_to_customer", "taskReferenceName": "send_notification_subworkflow", "description": "{\"description\":null}", @@ -34,34 +33,14 @@ "customer_id": "${workflow.input.customer_id}" }, "type": "SUB_WORKFLOW", - "dynamicTaskNameParam": null, - "caseValueParam": null, - "caseExpression": null, - "expression": null, - "evaluatorType": null, - "scriptExpression": null, - "decisionCases": null, - "dynamicForkJoinTasksParam": null, - "dynamicForkTasksParam": null, - "dynamicForkTasksInputParamName": null, - "defaultCase": null, - "forkTasks": null, "startDelay": 0, "subWorkflowParam": { "name": "NOTIFICATION_send_to_customer", - "version": 1, - "taskToDomain": null, - "workflowDefinition": null + "version": 1 }, - "joinOn": null, - "sink": null, "optional": false, - "taskDefinition": null, "rateLimited": false, - "defaultExclusiveJoinTask": null, - "asyncComplete": false, - "loopCondition": null, - "loopOver": null + "asyncComplete": false } ] }, diff --git a/test/ConductorSharp.Engine.Tests/Samples/Workflows/DecisionInDecision.json b/test/ConductorSharp.Engine.Tests/Samples/Workflows/DecisionInDecision.json index ece94733..252152bd 100644 --- a/test/ConductorSharp.Engine.Tests/Samples/Workflows/DecisionInDecision.json +++ b/test/ConductorSharp.Engine.Tests/Samples/Workflows/DecisionInDecision.json @@ -26,24 +26,16 @@ "decisionCases": { "YES": [ { - "queryExpression": null, "name": "DECISION_second_send_notification_decision", "taskReferenceName": "second_send_notification_decision", - "description": null, "inputParameters": { "case_value_param": "${workflow.input.should_send_notification}" }, "type": "DECISION", - "dynamicTaskNameParam": null, "caseValueParam": "case_value_param", - "caseExpression": null, - "expression": null, - "evaluatorType": null, - "scriptExpression": null, "decisionCases": { "YES": [ { - "queryExpression": null, "name": "NOTIFICATION_send_to_customer", "taskReferenceName": "send_notification_subworkflow", "description": "{\"description\":null}", @@ -51,53 +43,21 @@ "customer_id": "${workflow.input.customer_id}" }, "type": "SUB_WORKFLOW", - "dynamicTaskNameParam": null, - "caseValueParam": null, - "caseExpression": null, - "expression": null, - "evaluatorType": null, - "scriptExpression": null, - "decisionCases": null, - "dynamicForkJoinTasksParam": null, - "dynamicForkTasksParam": null, - "dynamicForkTasksInputParamName": null, - "defaultCase": null, - "forkTasks": null, "startDelay": 0, "subWorkflowParam": { "name": "NOTIFICATION_send_to_customer", - "version": 1, - "taskToDomain": null, - "workflowDefinition": null + "version": 1 }, - "joinOn": null, - "sink": null, "optional": false, - "taskDefinition": null, "rateLimited": false, - "defaultExclusiveJoinTask": null, - "asyncComplete": false, - "loopCondition": null, - "loopOver": null + "asyncComplete": false } ] }, - "dynamicForkJoinTasksParam": null, - "dynamicForkTasksParam": null, - "dynamicForkTasksInputParamName": null, - "defaultCase": null, - "forkTasks": null, "startDelay": 0, - "subWorkflowParam": null, - "joinOn": null, - "sink": null, "optional": false, - "taskDefinition": null, "rateLimited": false, - "defaultExclusiveJoinTask": null, - "asyncComplete": false, - "loopCondition": null, - "loopOver": null + "asyncComplete": false } ] }, diff --git a/test/ConductorSharp.Engine.Tests/Samples/Workflows/TerminateTaskWorkflow.json b/test/ConductorSharp.Engine.Tests/Samples/Workflows/TerminateTaskWorkflow.json index e46c2ed0..acea14b3 100644 --- a/test/ConductorSharp.Engine.Tests/Samples/Workflows/TerminateTaskWorkflow.json +++ b/test/ConductorSharp.Engine.Tests/Samples/Workflows/TerminateTaskWorkflow.json @@ -26,7 +26,6 @@ "decisionCases": { "value": [ { - "queryExpression": null, "name": "TERMINATE_decision_terminate", "taskReferenceName": "decision_terminate", "description": "{\"description\":null}", @@ -37,29 +36,10 @@ "terminationStatus": "COMPLETED" }, "type": "TERMINATE", - "dynamicTaskNameParam": null, - "caseValueParam": null, - "caseExpression": null, - "expression": null, - "evaluatorType": null, - "scriptExpression": null, - "decisionCases": null, - "dynamicForkJoinTasksParam": null, - "dynamicForkTasksParam": null, - "dynamicForkTasksInputParamName": null, - "defaultCase": null, - "forkTasks": null, "startDelay": 0, - "subWorkflowParam": null, - "joinOn": null, - "sink": null, "optional": false, - "taskDefinition": null, "rateLimited": false, - "defaultExclusiveJoinTask": null, - "asyncComplete": false, - "loopCondition": null, - "loopOver": null + "asyncComplete": false } ] }, @@ -98,7 +78,6 @@ "decisionCases": { "value": [ { - "queryExpression": null, "name": "TERMINATE_switch_terminate", "taskReferenceName": "switch_terminate", "description": "{\"description\":null}", @@ -109,29 +88,10 @@ "terminationStatus": "FAILED" }, "type": "TERMINATE", - "dynamicTaskNameParam": null, - "caseValueParam": null, - "caseExpression": null, - "expression": null, - "evaluatorType": null, - "scriptExpression": null, - "decisionCases": null, - "dynamicForkJoinTasksParam": null, - "dynamicForkTasksParam": null, - "dynamicForkTasksInputParamName": null, - "defaultCase": null, - "forkTasks": null, "startDelay": 0, - "subWorkflowParam": null, - "joinOn": null, - "sink": null, "optional": false, - "taskDefinition": null, "rateLimited": false, - "defaultExclusiveJoinTask": null, - "asyncComplete": false, - "loopCondition": null, - "loopOver": null + "asyncComplete": false } ] },