From 7c8b4a1018d7af1494473d36b43db9ed17f0c1af Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sun, 18 Oct 2020 17:05:48 +0200 Subject: [PATCH] Add For activity builder extensions and add sample --- Samples.sln | 14 ++++ .../Activities/ReadLine/ReadLine.cs | 2 +- .../WriteLine/WriteLineBuilderExtensions.cs | 25 ++----- .../Elsa.Abstractions/Models/Variables.cs | 2 + .../Services/IWorkflowHost.cs | 13 ++++ .../Models/WorkflowExecutionContext.cs | 3 +- .../Activities/ControlFlow/For/For.cs | 30 ++++++-- .../ControlFlow/For/ForBuilderExtensions.cs | 71 +++++++++++++++++++ .../Activities/ControlFlow/For/Operator.cs | 10 +++ .../SetVariableBuilderExtensions.cs | 32 +++++++++ .../Elsa.Core/Elsa.Core.csproj.DotSettings | 2 + .../ElsaServiceCollectionExtensions.cs | 2 - .../Handlers/SelectOptionsProvider.cs | 2 - .../Serialization/DefaultJsonSerializer.cs | 1 - src/core/Elsa.Core/Services/WorkflowHost.cs | 23 +++++- .../Elsa.Core/Services/WorkflowRegistry.cs | 2 - .../Elsa.Samples.DistributedLock/Program.cs | 2 - .../Elsa.Samples.ForEachConsole.csproj | 16 +++++ .../LoopingWorkflow.cs | 30 ++++++++ .../Elsa.Samples.ForEachConsole/Program.cs | 32 +++++++++ .../HelloWorld.cs | 13 ++++ .../Elsa.Samples.HelloWorldConsole/Program.cs | 19 ++--- .../HelloHttpWorkflow.cs | 3 + .../Elsa.Samples.HelloWorldHttp/Startup.cs | 1 + .../Elsa.Samples.ReadLineEchoConsole.csproj | 16 +++++ .../Program.cs | 37 ++++++++++ .../Elsa.Samples.Serialization/Program.cs | 1 - src/samples/Elsa.Samples.Timers/Program.cs | 1 - 28 files changed, 348 insertions(+), 57 deletions(-) create mode 100644 src/core/Elsa.Core/Activities/ControlFlow/For/ForBuilderExtensions.cs create mode 100644 src/core/Elsa.Core/Activities/ControlFlow/For/Operator.cs create mode 100644 src/core/Elsa.Core/Activities/Primitives/SetVariable/SetVariableBuilderExtensions.cs create mode 100644 src/core/Elsa.Core/Elsa.Core.csproj.DotSettings create mode 100644 src/samples/Elsa.Samples.ForEachConsole/Elsa.Samples.ForEachConsole.csproj create mode 100644 src/samples/Elsa.Samples.ForEachConsole/LoopingWorkflow.cs create mode 100644 src/samples/Elsa.Samples.ForEachConsole/Program.cs create mode 100644 src/samples/Elsa.Samples.HelloWorldConsole/HelloWorld.cs create mode 100644 src/samples/Elsa.Samples.ReadLineEchoConsole/Elsa.Samples.ReadLineEchoConsole.csproj create mode 100644 src/samples/Elsa.Samples.ReadLineEchoConsole/Program.cs diff --git a/Samples.sln b/Samples.sln index e707556df..d9f4d2aa0 100644 --- a/Samples.sln +++ b/Samples.sln @@ -90,6 +90,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "locking", "locking", "{7CD5 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YesSql.Provider.Sqlite.InMemory", "src\core\YesSql.Provider.Sqlite.InMemory\YesSql.Provider.Sqlite.InMemory.csproj", "{E2D63391-1986-45C8-A18F-4D58F3D71057}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.ForEachConsole", "src\samples\Elsa.Samples.ForEachConsole\Elsa.Samples.ForEachConsole.csproj", "{F755FB1F-72FB-4F7B-8270-F5F40F4D6952}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.ReadLineEchoConsole", "src\samples\Elsa.Samples.ReadLineEchoConsole\Elsa.Samples.ReadLineEchoConsole.csproj", "{867CB845-B803-4D40-9360-3D11ADBD9CE9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -209,6 +213,14 @@ Global {E2D63391-1986-45C8-A18F-4D58F3D71057}.Debug|Any CPU.Build.0 = Debug|Any CPU {E2D63391-1986-45C8-A18F-4D58F3D71057}.Release|Any CPU.ActiveCfg = Release|Any CPU {E2D63391-1986-45C8-A18F-4D58F3D71057}.Release|Any CPU.Build.0 = Release|Any CPU + {F755FB1F-72FB-4F7B-8270-F5F40F4D6952}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F755FB1F-72FB-4F7B-8270-F5F40F4D6952}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F755FB1F-72FB-4F7B-8270-F5F40F4D6952}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F755FB1F-72FB-4F7B-8270-F5F40F4D6952}.Release|Any CPU.Build.0 = Release|Any CPU + {867CB845-B803-4D40-9360-3D11ADBD9CE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {867CB845-B803-4D40-9360-3D11ADBD9CE9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {867CB845-B803-4D40-9360-3D11ADBD9CE9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {867CB845-B803-4D40-9360-3D11ADBD9CE9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -250,6 +262,8 @@ Global {EBD49CCA-5400-4C36-B5DF-7B28190AA323} = {7CD5C8D5-EC78-4A99-A514-F01CA7197AC8} {150EF356-E8BC-4922-91C2-362017479409} = {7CD5C8D5-EC78-4A99-A514-F01CA7197AC8} {E2D63391-1986-45C8-A18F-4D58F3D71057} = {35F44BE9-13D0-417C-A01A-F0787BEE6DC3} + {F755FB1F-72FB-4F7B-8270-F5F40F4D6952} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A} + {867CB845-B803-4D40-9360-3D11ADBD9CE9} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8B0975FD-7050-48B0-88C5-48C33378E158} diff --git a/src/activities/Elsa.Activities.Console/Activities/ReadLine/ReadLine.cs b/src/activities/Elsa.Activities.Console/Activities/ReadLine/ReadLine.cs index c0db887f3..8ca4ef24d 100644 --- a/src/activities/Elsa.Activities.Console/Activities/ReadLine/ReadLine.cs +++ b/src/activities/Elsa.Activities.Console/Activities/ReadLine/ReadLine.cs @@ -50,6 +50,6 @@ namespace Elsa.Activities.Console return Execute(receivedInput); } - private IActivityExecutionResult Execute(string receivedInput) => Done((object)receivedInput); + private IActivityExecutionResult Execute(string receivedInput) => Done(receivedInput); } } \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Console/Activities/WriteLine/WriteLineBuilderExtensions.cs b/src/activities/Elsa.Activities.Console/Activities/WriteLine/WriteLineBuilderExtensions.cs index f11cf2a32..03537baa6 100644 --- a/src/activities/Elsa.Activities.Console/Activities/WriteLine/WriteLineBuilderExtensions.cs +++ b/src/activities/Elsa.Activities.Console/Activities/WriteLine/WriteLineBuilderExtensions.cs @@ -8,25 +8,12 @@ namespace Elsa.Activities.Console { public static class WriteLineBuilderExtensions { - public static IOutcomeBuilder WriteLine(this IBuilder builder, - Action> setup) => WriteLine(builder.Then(setup)); - - public static IOutcomeBuilder WriteLine(this IBuilder builder, Func text) => - builder.WriteLine(activity => activity.Set(x => x.Text, text)); - - public static IOutcomeBuilder WriteLine(this IBuilder builder, - Func> text) => - builder.WriteLine(activity => activity.Set(x => x.Text, text)); - - public static IOutcomeBuilder WriteLine(this IBuilder builder, Func text) => - builder.WriteLine(activity => activity.Set(x => x.Text, text)); - - public static IOutcomeBuilder WriteLine(this IBuilder builder, Func> text) => - builder.WriteLine(activity => activity.Set(x => x.Text, text)); - - public static IOutcomeBuilder WriteLine(this IBuilder builder, string text) => - builder.WriteLine(activity => activity.Set(x => x.Text, text)); - + public static IOutcomeBuilder WriteLine(this IBuilder builder, Action> setup) => WriteLine(builder.Then(setup)); + public static IOutcomeBuilder WriteLine(this IBuilder builder, Func text) => builder.WriteLine(activity => activity.Set(x => x.Text, text)); + public static IOutcomeBuilder WriteLine(this IBuilder builder, Func> text) => builder.WriteLine(activity => activity.Set(x => x.Text, text)); + public static IOutcomeBuilder WriteLine(this IBuilder builder, Func text) => builder.WriteLine(activity => activity.Set(x => x.Text, text)); + public static IOutcomeBuilder WriteLine(this IBuilder builder, Func> text) => builder.WriteLine(activity => activity.Set(x => x.Text, text)); + public static IOutcomeBuilder WriteLine(this IBuilder builder, string text) => builder.WriteLine(activity => activity.Set(x => x.Text, text)); private static IOutcomeBuilder WriteLine(IActivityBuilder writeLine) => writeLine.When(OutcomeNames.Done); } } \ No newline at end of file diff --git a/src/core/Elsa.Abstractions/Models/Variables.cs b/src/core/Elsa.Abstractions/Models/Variables.cs index cd8cb8bc1..93b47cfe7 100644 --- a/src/core/Elsa.Abstractions/Models/Variables.cs +++ b/src/core/Elsa.Abstractions/Models/Variables.cs @@ -7,6 +7,7 @@ namespace Elsa.Models { public Variables() { + Data = new JObject(); } public Variables(Variables other) : this(other.Data) @@ -21,6 +22,7 @@ namespace Elsa.Models public JObject Data { get; set; } public JToken? Get(string name) => Has(name) ? Data[name] : default; + public T Get(string name) => Has(name) ? Data.Value(name) : default!; public Variables Set(string name, JToken value) { diff --git a/src/core/Elsa.Abstractions/Services/IWorkflowHost.cs b/src/core/Elsa.Abstractions/Services/IWorkflowHost.cs index 33b680f14..cd8245aa2 100644 --- a/src/core/Elsa.Abstractions/Services/IWorkflowHost.cs +++ b/src/core/Elsa.Abstractions/Services/IWorkflowHost.cs @@ -1,5 +1,6 @@ using System.Threading; using System.Threading.Tasks; +using Elsa.Builders; using Elsa.Models; using Elsa.Services.Models; @@ -26,5 +27,17 @@ namespace Elsa.Services object? input = default, string? correlationId = default, CancellationToken cancellationToken = default); + + ValueTask RunWorkflowAsync( + string? activityId = default, + object? input = default, + string? correlationId = default, + CancellationToken cancellationToken = default) where T:IWorkflow; + + ValueTask RunWorkflowAsync( + WorkflowInstance workflowInstance, + string? activityId = default, + object? input = default, + CancellationToken cancellationToken = default) where T:IWorkflow; } } \ No newline at end of file diff --git a/src/core/Elsa.Abstractions/Services/Models/WorkflowExecutionContext.cs b/src/core/Elsa.Abstractions/Services/Models/WorkflowExecutionContext.cs index 35a800671..57d9215c0 100644 --- a/src/core/Elsa.Abstractions/Services/Models/WorkflowExecutionContext.cs +++ b/src/core/Elsa.Abstractions/Services/Models/WorkflowExecutionContext.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Elsa.Comparers; using Elsa.Models; using Microsoft.Extensions.Localization; using Newtonsoft.Json.Linq; @@ -52,7 +51,7 @@ namespace Elsa.Services.Models public WorkflowStatus Status => WorkflowInstance.Status; public void SetVariable(string name, object? value) => WorkflowInstance.Variables.Set(name, JToken.FromObject(value!)); - public T GetVariable(string name) => (T)GetVariable(name)!; + public T GetVariable(string name) => WorkflowInstance.Variables.Get(name); public object? GetVariable(string name) => WorkflowInstance.Variables.Get(name); public void CompletePass() => IsFirstPass = false; public void Begin() => WorkflowInstance.Status = WorkflowStatus.Running; diff --git a/src/core/Elsa.Core/Activities/ControlFlow/For/For.cs b/src/core/Elsa.Core/Activities/ControlFlow/For/For.cs index 4979a8337..9a4b65239 100644 --- a/src/core/Elsa.Core/Activities/ControlFlow/For/For.cs +++ b/src/core/Elsa.Core/Activities/ControlFlow/For/For.cs @@ -1,3 +1,4 @@ +using System; using Elsa.ActivityResults; using Elsa.Attributes; using Elsa.Services; @@ -21,19 +22,34 @@ namespace Elsa.Activities.ControlFlow public int End { get; set; } [ActivityProperty(Hint = "An expression that evaluates to the incrementing number on each step.")] - public int Step { get; set; } + public int Step { get; set; } = 1; - private int? CurrentValue { get; set; } + [ActivityProperty(Hint = "The operator to use when comparing the current value against the end value.")] + public Operator Operator { get; set; } = Operator.LessThan; + + private int? CurrentValue + { + get => GetState(); + set => SetState(value); + } protected override IActivityExecutionResult OnExecute(ActivityExecutionContext context) { var currentValue = CurrentValue ?? Start; - - if (currentValue < End) + + var loop = Operator switch { - currentValue += Step; - CurrentValue = currentValue; - return Combine(Schedule(Id), Output(currentValue), Done(OutcomeNames.Iterate)); + Operator.LessThan => currentValue < End, + Operator.LessThanOrEqual => currentValue <= End, + Operator.GreaterThan => currentValue > End, + Operator.GreaterThanOrEqual => currentValue >= End, + _ => throw new NotSupportedException() + }; + + if (loop) + { + CurrentValue = currentValue + Step; + return Combine(Schedule(Id), Output(currentValue), Outcome(OutcomeNames.Iterate)); } CurrentValue = null; diff --git a/src/core/Elsa.Core/Activities/ControlFlow/For/ForBuilderExtensions.cs b/src/core/Elsa.Core/Activities/ControlFlow/For/ForBuilderExtensions.cs new file mode 100644 index 000000000..7f3f82d34 --- /dev/null +++ b/src/core/Elsa.Core/Activities/ControlFlow/For/ForBuilderExtensions.cs @@ -0,0 +1,71 @@ +using System; +using System.Threading.Tasks; +using Elsa.Builders; +using Elsa.Services; +using Elsa.Services.Models; + +// ReSharper disable once CheckNamespace +namespace Elsa.Activities.ControlFlow +{ + public static class ForBuilderExtensions + { + public static IActivityBuilder For(this IBuilder builder, Action> setup, Action iterate) => builder.Then(setup, branch => iterate(branch.When(OutcomeNames.Iterate))); + + public static IActivityBuilder For( + this IBuilder builder, + Func start, + Func end, + Func step, + Action iterate, + Operator op = Operator.LessThan) => + builder.For( + activity => activity + .Set(x => x.Start, start) + .Set(x => x.End, end) + .Set(x => x.Step, step) + .Set(x => x.Operator, op), + iterate); + + public static IActivityBuilder For(this IBuilder builder, Func start, Func end, Func step, Action iterate, Operator op = Operator.LessThan) => + builder.For( + activity => activity + .Set(x => x.Start, start) + .Set(x => x.End, end) + .Set(x => x.Step, step) + .Set(x => x.Operator, op), + iterate); + + public static IActivityBuilder For(this IBuilder builder, int start, int end, int step, Action iterate, Operator op = Operator.LessThan) => + builder.For( + activity => activity + .Set(x => x.Start, start) + .Set(x => x.End, end) + .Set(x => x.Step, step) + .Set(x => x.Operator, op), + iterate); + + public static IActivityBuilder For(this IBuilder builder, Func start, Func end, Action iterate, Operator op = Operator.LessThan) => + builder.For( + activity => activity + .Set(x => x.Start, start) + .Set(x => x.End, end) + .Set(x => x.Operator, op), + iterate); + + public static IActivityBuilder For(this IBuilder builder, Func start, Func end, Action iterate, Operator op = Operator.LessThan) => + builder.For( + activity => activity + .Set(x => x.Start, start) + .Set(x => x.End, end) + .Set(x => x.Operator, op), + iterate); + + public static IActivityBuilder For(this IBuilder builder, int start, int end, Action iterate, Operator op = Operator.LessThan) => + builder.For( + activity => activity + .Set(x => x.Start, start) + .Set(x => x.End, end) + .Set(x => x.Operator, op), + iterate); + } +} \ No newline at end of file diff --git a/src/core/Elsa.Core/Activities/ControlFlow/For/Operator.cs b/src/core/Elsa.Core/Activities/ControlFlow/For/Operator.cs new file mode 100644 index 000000000..6ebebd770 --- /dev/null +++ b/src/core/Elsa.Core/Activities/ControlFlow/For/Operator.cs @@ -0,0 +1,10 @@ +namespace Elsa.Activities.ControlFlow +{ + public enum Operator + { + LessThan, + LessThanOrEqual, + GreaterThan, + GreaterThanOrEqual + } +} \ No newline at end of file diff --git a/src/core/Elsa.Core/Activities/Primitives/SetVariable/SetVariableBuilderExtensions.cs b/src/core/Elsa.Core/Activities/Primitives/SetVariable/SetVariableBuilderExtensions.cs new file mode 100644 index 000000000..9963967ab --- /dev/null +++ b/src/core/Elsa.Core/Activities/Primitives/SetVariable/SetVariableBuilderExtensions.cs @@ -0,0 +1,32 @@ +using System; +using System.Threading.Tasks; +using Elsa.Activities.Primitives; +using Elsa.Builders; +using Elsa.Services.Models; + +// ReSharper disable once CheckNamespace +namespace Elsa.Activities.ControlFlow +{ + public static class SetVariableBuilderExtensions + { + public static IOutcomeBuilder SetVariable(this IBuilder builder, Action> setup) => builder.Then(setup).When(OutcomeNames.Done); + + public static IOutcomeBuilder SetVariable(this IBuilder builder, string name, Func value) => + builder.SetVariable( + activity => activity + .Set(x => x.VariableName, name) + .Set(x => x.Value, value)); + + public static IOutcomeBuilder SetVariable(this IBuilder builder, string name, Func value) => + builder.SetVariable( + activity => activity + .Set(x => x.VariableName, name) + .Set(x => x.Value, value)); + + public static IOutcomeBuilder SetVariable(this IBuilder builder, string name, object? value) => + builder.SetVariable( + activity => activity + .Set(x => x.VariableName, name) + .Set(x => x.Value, value)); + } +} \ No newline at end of file diff --git a/src/core/Elsa.Core/Elsa.Core.csproj.DotSettings b/src/core/Elsa.Core/Elsa.Core.csproj.DotSettings new file mode 100644 index 000000000..30aa63108 --- /dev/null +++ b/src/core/Elsa.Core/Elsa.Core.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs b/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs index ef804d411..bac7236a4 100644 --- a/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs +++ b/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs @@ -17,14 +17,12 @@ using Elsa.Metadata; using Elsa.Metadata.Handlers; using Elsa.Runtime; using Elsa.Serialization; -using Elsa.Serialization.Formatters; using Elsa.Services; using Elsa.StartupTasks; using Elsa.Triggers; using Elsa.WorkflowProviders; using MediatR; using Microsoft.Extensions.DependencyInjection.Extensions; -using Newtonsoft.Json; using NodaTime; using Rebus.Handlers; diff --git a/src/core/Elsa.Core/Metadata/Handlers/SelectOptionsProvider.cs b/src/core/Elsa.Core/Metadata/Handlers/SelectOptionsProvider.cs index 2b160eb4e..1eea1a589 100644 --- a/src/core/Elsa.Core/Metadata/Handlers/SelectOptionsProvider.cs +++ b/src/core/Elsa.Core/Metadata/Handlers/SelectOptionsProvider.cs @@ -1,8 +1,6 @@ using System.Linq; using System.Reflection; using Elsa.Attributes; -using Elsa.Serialization; -using Newtonsoft.Json; using Newtonsoft.Json.Linq; using JsonSerializer = Newtonsoft.Json.JsonSerializer; diff --git a/src/core/Elsa.Core/Serialization/DefaultJsonSerializer.cs b/src/core/Elsa.Core/Serialization/DefaultJsonSerializer.cs index 036e3d8bc..16cdc1e8d 100644 --- a/src/core/Elsa.Core/Serialization/DefaultJsonSerializer.cs +++ b/src/core/Elsa.Core/Serialization/DefaultJsonSerializer.cs @@ -1,4 +1,3 @@ -using System; using Elsa.Converters; using Newtonsoft.Json; using Newtonsoft.Json.Linq; diff --git a/src/core/Elsa.Core/Services/WorkflowHost.cs b/src/core/Elsa.Core/Services/WorkflowHost.cs index e706bbfb7..5c8fcef77 100644 --- a/src/core/Elsa.Core/Services/WorkflowHost.cs +++ b/src/core/Elsa.Core/Services/WorkflowHost.cs @@ -4,13 +4,13 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Elsa.ActivityResults; +using Elsa.Builders; using Elsa.Events; using Elsa.Exceptions; using Elsa.Models; using Elsa.Services.Models; using Elsa.Triggers; using MediatR; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace Elsa.Services @@ -24,6 +24,7 @@ namespace Elsa.Services private readonly IWorkflowRegistry _workflowRegistry; private readonly IWorkflowFactory _workflowFactory; + private readonly IWorkflowBuilder _workflowBuilder; private readonly IMediator _mediator; private readonly IServiceProvider _serviceProvider; private readonly IEnumerable _triggerProviders; @@ -32,6 +33,7 @@ namespace Elsa.Services public WorkflowHost( IWorkflowRegistry workflowRegistry, IWorkflowFactory workflowFactory, + IWorkflowBuilder workflowBuilder, IMediator mediator, IServiceProvider serviceProvider, IEnumerable triggerProviders, @@ -39,6 +41,7 @@ namespace Elsa.Services { _workflowRegistry = workflowRegistry; _workflowFactory = workflowFactory; + _workflowBuilder = workflowBuilder; _mediator = mediator; _serviceProvider = serviceProvider; _triggerProviders = triggerProviders; @@ -60,6 +63,22 @@ namespace Elsa.Services return await RunWorkflowAsync(workflowBlueprint, workflowInstance, activityId, input, cancellationToken); } + public async ValueTask RunWorkflowAsync( + string? activityId = default, + object? input = default, + string? correlationId = default, + CancellationToken cancellationToken = default) + where T : IWorkflow => + await RunWorkflowAsync(_workflowBuilder.Build(), activityId, input, correlationId, cancellationToken); + + public async ValueTask RunWorkflowAsync( + WorkflowInstance workflowInstance, + string? activityId = default, + object? input = default, + CancellationToken cancellationToken = default) + where T : IWorkflow => + await RunWorkflowAsync(_workflowBuilder.Build(), workflowInstance, activityId, input, cancellationToken); + public async ValueTask RunWorkflowAsync( WorkflowInstance workflowInstance, string? activityId = default, @@ -202,7 +221,7 @@ namespace Elsa.Services await _mediator.Publish(new ActivityExecuting(activityExecutionContext), cancellationToken); await result.ExecuteAsync(activityExecutionContext, cancellationToken); await _mediator.Publish(new ActivityExecuted(activityExecutionContext), cancellationToken); - + activityOperation = Execute; workflowExecutionContext.CompletePass(); } diff --git a/src/core/Elsa.Core/Services/WorkflowRegistry.cs b/src/core/Elsa.Core/Services/WorkflowRegistry.cs index 6efd91eba..3b098a1b4 100644 --- a/src/core/Elsa.Core/Services/WorkflowRegistry.cs +++ b/src/core/Elsa.Core/Services/WorkflowRegistry.cs @@ -1,11 +1,9 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Elsa.Models; using Elsa.Services.Models; -using Microsoft.Extensions.DependencyInjection; using Open.Linq.AsyncExtensions; namespace Elsa.Services diff --git a/src/samples/Elsa.Samples.DistributedLock/Program.cs b/src/samples/Elsa.Samples.DistributedLock/Program.cs index 1d7ab16dc..370cc74d2 100644 --- a/src/samples/Elsa.Samples.DistributedLock/Program.cs +++ b/src/samples/Elsa.Samples.DistributedLock/Program.cs @@ -2,8 +2,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using NodaTime; using System.Threading.Tasks; -using Elsa.DistributedLocking.AzureBlob; -using System; using Elsa.DistributedLocking.Redis; using YesSql.Provider.Sqlite; diff --git a/src/samples/Elsa.Samples.ForEachConsole/Elsa.Samples.ForEachConsole.csproj b/src/samples/Elsa.Samples.ForEachConsole/Elsa.Samples.ForEachConsole.csproj new file mode 100644 index 000000000..7fbd68615 --- /dev/null +++ b/src/samples/Elsa.Samples.ForEachConsole/Elsa.Samples.ForEachConsole.csproj @@ -0,0 +1,16 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + diff --git a/src/samples/Elsa.Samples.ForEachConsole/LoopingWorkflow.cs b/src/samples/Elsa.Samples.ForEachConsole/LoopingWorkflow.cs new file mode 100644 index 000000000..cba134d9c --- /dev/null +++ b/src/samples/Elsa.Samples.ForEachConsole/LoopingWorkflow.cs @@ -0,0 +1,30 @@ +using System; +using Elsa.Activities.Console; +using Elsa.Activities.ControlFlow; +using Elsa.Builders; + +namespace Elsa.Samples.ForEachConsole +{ + /// + /// This workflow prompts the user to enter an integer start value, then iterates back from that value to 0. + /// The workflow also demonstrates retrieving runtime values such as user input. + /// + public class LoopingWorkflow : IWorkflow + { + public void Build(IWorkflowBuilder builder) + { + builder + .WriteLine("Enter a number:") + .ReadLine() + .SetVariable("From", context => int.Parse(((string)context.Input)!)) + .WriteLine(context => $"Counting down from {Math.Abs(context.GetVariable("From")!)} to 0...") + .For( + context => context.GetVariable("From"), + _ => 0, + _ => -1, + iterate => iterate.WriteLine(context => $"Iteration {context.Input}"), + Operator.GreaterThanOrEqual) + .WriteLine("Done."); + } + } +} \ No newline at end of file diff --git a/src/samples/Elsa.Samples.ForEachConsole/Program.cs b/src/samples/Elsa.Samples.ForEachConsole/Program.cs new file mode 100644 index 000000000..137f6a88e --- /dev/null +++ b/src/samples/Elsa.Samples.ForEachConsole/Program.cs @@ -0,0 +1,32 @@ +using System.Threading.Tasks; +using Elsa.Services; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Samples.ForEachConsole +{ + /// + /// Demonstrates a workflow with a For looping construct. + /// + static class Program + { + private static async Task Main() + { + // Create a service container with Elsa services. + var services = new ServiceCollection() + .AddElsa() + .AddConsoleActivities() + .AddWorkflow() + .BuildServiceProvider(); + + // Run startup actions (not needed when registering Elsa with a Host). + var startupRunner = services.GetRequiredService(); + await startupRunner.StartupAsync(); + + // Get the workflow host. + var workflowHost = services.GetService(); + + // Execute the workflow. + await workflowHost.RunWorkflowAsync(); + } + } +} \ No newline at end of file diff --git a/src/samples/Elsa.Samples.HelloWorldConsole/HelloWorld.cs b/src/samples/Elsa.Samples.HelloWorldConsole/HelloWorld.cs new file mode 100644 index 000000000..96a147619 --- /dev/null +++ b/src/samples/Elsa.Samples.HelloWorldConsole/HelloWorld.cs @@ -0,0 +1,13 @@ +using Elsa.Activities.Console; +using Elsa.Builders; + +namespace Elsa.Samples.HelloWorldConsole +{ + /// + /// A basic workflow with just one WriteLine activity. + /// + public class HelloWorld : IWorkflow + { + public void Build(IWorkflowBuilder builder) => builder.WriteLine("Hello World!"); + } +} \ No newline at end of file diff --git a/src/samples/Elsa.Samples.HelloWorldConsole/Program.cs b/src/samples/Elsa.Samples.HelloWorldConsole/Program.cs index a1b3b18a8..6f83693de 100644 --- a/src/samples/Elsa.Samples.HelloWorldConsole/Program.cs +++ b/src/samples/Elsa.Samples.HelloWorldConsole/Program.cs @@ -1,7 +1,4 @@ -using System; -using System.Threading.Tasks; -using Elsa.Activities.Console; -using Elsa.Builders; +using System.Threading.Tasks; using Elsa.Services; using Microsoft.Extensions.DependencyInjection; @@ -15,26 +12,18 @@ namespace Elsa.Samples.HelloWorldConsole var services = new ServiceCollection() .AddElsa() .AddConsoleActivities() - .AddSingleton(Console.In) + .AddWorkflow() .BuildServiceProvider(); // Run startup actions (not needed when registering Elsa with a Host). var startupRunner = services.GetRequiredService(); await startupRunner.StartupAsync(); - // Build a new workflow. - var workflow = services.GetService() - .WriteLine("Hello World!") - .WriteLine("What's your name?") - .ReadLine() - .WriteLine(context => $"Greetings, {context.Input}!") - .Build(); - - // Get the workflow host. + // Get a workflow host. var workflowHost = services.GetService(); // Execute the workflow. - await workflowHost.RunWorkflowAsync(workflow); + await workflowHost.RunWorkflowAsync(); } } } \ No newline at end of file diff --git a/src/samples/Elsa.Samples.HelloWorldHttp/HelloHttpWorkflow.cs b/src/samples/Elsa.Samples.HelloWorldHttp/HelloHttpWorkflow.cs index caaf97270..3eae43d8a 100644 --- a/src/samples/Elsa.Samples.HelloWorldHttp/HelloHttpWorkflow.cs +++ b/src/samples/Elsa.Samples.HelloWorldHttp/HelloHttpWorkflow.cs @@ -4,6 +4,9 @@ using Elsa.Builders; namespace Elsa.Samples.HelloWorldHttp { + /// + /// A workflow that is triggered when HTTP requests are made to /hello and writes a response. + /// public class HelloHttpWorkflow : IWorkflow { public void Build(IWorkflowBuilder builder) diff --git a/src/samples/Elsa.Samples.HelloWorldHttp/Startup.cs b/src/samples/Elsa.Samples.HelloWorldHttp/Startup.cs index b9bc0de03..38dd3705c 100644 --- a/src/samples/Elsa.Samples.HelloWorldHttp/Startup.cs +++ b/src/samples/Elsa.Samples.HelloWorldHttp/Startup.cs @@ -16,6 +16,7 @@ namespace Elsa.Samples.HelloWorldHttp public void Configure(IApplicationBuilder app) { + // Add HTTP activities middleware. app.UseHttpActivities(); } } diff --git a/src/samples/Elsa.Samples.ReadLineEchoConsole/Elsa.Samples.ReadLineEchoConsole.csproj b/src/samples/Elsa.Samples.ReadLineEchoConsole/Elsa.Samples.ReadLineEchoConsole.csproj new file mode 100644 index 000000000..7fbd68615 --- /dev/null +++ b/src/samples/Elsa.Samples.ReadLineEchoConsole/Elsa.Samples.ReadLineEchoConsole.csproj @@ -0,0 +1,16 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + diff --git a/src/samples/Elsa.Samples.ReadLineEchoConsole/Program.cs b/src/samples/Elsa.Samples.ReadLineEchoConsole/Program.cs new file mode 100644 index 000000000..680ba12d7 --- /dev/null +++ b/src/samples/Elsa.Samples.ReadLineEchoConsole/Program.cs @@ -0,0 +1,37 @@ +using System.Threading.Tasks; +using Elsa.Activities.Console; +using Elsa.Builders; +using Elsa.Services; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Samples.ReadLineEchoConsole +{ + class Program + { + static async Task Main(string[] args) + { + // Create a service container with Elsa services. + var services = new ServiceCollection() + .AddElsa() + .AddConsoleActivities() + .BuildServiceProvider(); + + // Run startup actions (not needed when registering Elsa with a Host). + var startupRunner = services.GetRequiredService(); + await startupRunner.StartupAsync(); + + // Build a new workflow. + var workflow = services.GetService() + .WriteLine("What's your name?") + .ReadLine() + .WriteLine(context => $"Greetings, {context.Input}!") + .Build(); + + // Get the workflow host. + var workflowHost = services.GetService(); + + // Execute the workflow. + await workflowHost.RunWorkflowAsync(workflow); + } + } +} \ No newline at end of file diff --git a/src/samples/Elsa.Samples.Serialization/Program.cs b/src/samples/Elsa.Samples.Serialization/Program.cs index 1341be5d0..66dc0a6c8 100644 --- a/src/samples/Elsa.Samples.Serialization/Program.cs +++ b/src/samples/Elsa.Samples.Serialization/Program.cs @@ -1,7 +1,6 @@ using System; using System.Threading.Tasks; using Elsa.Activities.Console; -using Elsa.Expressions; using Elsa.Models; using Elsa.Scripting.Liquid.Services; using Elsa.Serialization; diff --git a/src/samples/Elsa.Samples.Timers/Program.cs b/src/samples/Elsa.Samples.Timers/Program.cs index 21959d5d2..7af99adf7 100644 --- a/src/samples/Elsa.Samples.Timers/Program.cs +++ b/src/samples/Elsa.Samples.Timers/Program.cs @@ -1,7 +1,6 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; using NodaTime; using YesSql.Provider.Sqlite;