From 642e700c3ded4c9573e3f649b0ebbefd8bd8e9b4 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Thu, 11 Jan 2024 21:00:35 +0100 Subject: [PATCH 1/8] Refactor MassTransitActivityTypeProvider (#4792) Fixed the Message input descriptor for dynamically provided MassTransit PublishMessage activities. --- .../Activities/PublishMessage.cs | 6 +- .../MassTransitActivityTypeProvider.cs | 68 ++++++++----------- 2 files changed, 33 insertions(+), 41 deletions(-) diff --git a/src/modules/Elsa.MassTransit/Activities/PublishMessage.cs b/src/modules/Elsa.MassTransit/Activities/PublishMessage.cs index e5972aa46..1802f3bd8 100644 --- a/src/modules/Elsa.MassTransit/Activities/PublishMessage.cs +++ b/src/modules/Elsa.MassTransit/Activities/PublishMessage.cs @@ -6,6 +6,7 @@ using Elsa.MassTransit.Implementations; using Elsa.Workflows; using Elsa.Workflows.Attributes; using Elsa.Workflows.Models; +using Elsa.Workflows.UIHints; using MassTransit; namespace Elsa.MassTransit.Activities; @@ -29,7 +30,10 @@ public class PublishMessage : CodeActivity /// /// The message to send. Must be a concrete implementation of the configured . /// - [Input(Description = "The message to send. Must be a concrete implementation of the configured message type.")] + [Input( + Description = "The message to send. Must be a concrete implementation of the configured message type.", + UIHint = InputUIHints.MultiLine + )] public Input Message { get; set; } = default!; /// diff --git a/src/modules/Elsa.MassTransit/Implementations/MassTransitActivityTypeProvider.cs b/src/modules/Elsa.MassTransit/Implementations/MassTransitActivityTypeProvider.cs index 75d9b32a6..e2dabe143 100644 --- a/src/modules/Elsa.MassTransit/Implementations/MassTransitActivityTypeProvider.cs +++ b/src/modules/Elsa.MassTransit/Implementations/MassTransitActivityTypeProvider.cs @@ -6,8 +6,8 @@ using Elsa.MassTransit.Options; using Elsa.Workflows; using Elsa.Workflows.Attributes; using Elsa.Workflows.Contracts; -using Elsa.Workflows.UIHints; using Elsa.Workflows.Helpers; +using Elsa.Workflows.Management; using Elsa.Workflows.Models; using Humanizer; using Microsoft.Extensions.Options; @@ -17,40 +17,31 @@ namespace Elsa.MassTransit.Implementations; /// /// Provides activities to the system from the configured MassTransit message types. /// -public class MassTransitActivityTypeProvider : IActivityProvider +public class MassTransitActivityTypeProvider(IActivityFactory activityFactory, IOptions options, IActivityDescriber activityDescriber) : IActivityProvider { - private readonly IActivityFactory _activityFactory; - private readonly MassTransitActivityOptions _options; - - /// - /// Constructor. - /// - public MassTransitActivityTypeProvider(IActivityFactory activityFactory, IOptions options) - { - _activityFactory = activityFactory; - _options = options.Value; - } - /// - public ValueTask> GetDescriptorsAsync(CancellationToken cancellationToken = default) + public async ValueTask> GetDescriptorsAsync(CancellationToken cancellationToken = default) { - var messageTypes = _options.MessageTypes; - var descriptors = CreateDescriptors(messageTypes).ToList(); - return new(descriptors); + var messageTypes = options.Value.MessageTypes; + var descriptors = await CreateDescriptorsAsync(messageTypes, cancellationToken); + return descriptors.ToList(); } - private IEnumerable CreateDescriptors(IEnumerable messageTypes) + private async Task> CreateDescriptorsAsync(IEnumerable messageTypes, CancellationToken cancellationToken = default) { + var descriptors = new List(); foreach (var messageType in messageTypes) { - yield return CreateMessageReceivedDescriptor(messageType); + descriptors.Add(await CreateMessageReceivedDescriptor(messageType, cancellationToken)); if(messageType.IsClass) - yield return CreatePublishMessageDescriptor(messageType); + descriptors.Add(await CreatePublishMessageDescriptor(messageType, cancellationToken)); } + + return descriptors; } - private ActivityDescriptor CreateMessageReceivedDescriptor(Type messageType) + private async Task CreateMessageReceivedDescriptor(Type messageType, CancellationToken cancellationToken = default) { var activityAttr = messageType.GetCustomAttribute(); var typeName = activityAttr?.Type ?? messageType.Name; @@ -61,6 +52,11 @@ public class MassTransitActivityTypeProvider : IActivityProvider var category = categoryAttr?.Category ?? activityAttr?.Category ?? "MassTransit"; var descriptionAttr = messageType.GetCustomAttribute(); var description = descriptionAttr?.Description ?? activityAttr?.Description; + + var outputDescriptor = await activityDescriber.DescribeOutputProperty(x => x.Result!, cancellationToken); + var openOutputType = typeof(Output<>); + var outputType = openOutputType.MakeGenericType(messageType); + outputDescriptor.Type = outputType; return new() { @@ -73,17 +69,11 @@ public class MassTransitActivityTypeProvider : IActivityProvider IsBrowsable = true, Outputs = { - new OutputDescriptor - { - Description = "The received message", - DisplayName = "Received Message", - Name = nameof(MessageReceived.Result), - Type = typeof(object) - } + outputDescriptor }, Constructor = context => { - var activity = _activityFactory.Create(context); + var activity = activityFactory.Create(context); activity.Type = fullTypeName; activity.MessageType = messageType; return activity; @@ -91,7 +81,7 @@ public class MassTransitActivityTypeProvider : IActivityProvider }; } - private ActivityDescriptor CreatePublishMessageDescriptor(Type messageType) + private async Task CreatePublishMessageDescriptor(Type messageType, CancellationToken cancellationToken = default) { var activityAttr = messageType.GetCustomAttribute(); var typeName = activityAttr?.Type ?? messageType.Name; @@ -104,6 +94,11 @@ public class MassTransitActivityTypeProvider : IActivityProvider var descriptionAttr = messageType.GetCustomAttribute(); var description = descriptionAttr?.Description ?? activityAttr?.Description; + var messageInputDescriptor = await activityDescriber.DescribeInputPropertyAsync(x => x.Message, cancellationToken: cancellationToken); + var openInputType = typeof(Input<>); + var inputType = openInputType.MakeGenericType(messageType); + messageInputDescriptor.Type = inputType; + return new() { TypeName = fullTypeName, @@ -115,18 +110,11 @@ public class MassTransitActivityTypeProvider : IActivityProvider IsBrowsable = true, Inputs = { - new InputDescriptor - { - Description = "The message to publish.", - UIHint = InputUIHints.MultiLine, - DisplayName = "Message", - Type = typeof(Input), - Name = nameof(PublishMessage.Message) - } + messageInputDescriptor }, Constructor = context => { - var activity = _activityFactory.Create(context); + var activity = activityFactory.Create(context); activity.Type = fullTypeName; activity.MessageType = messageType; return activity; From faa90fddf615b138cf789803ce3cb2204a2d329d Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Thu, 11 Jan 2024 21:02:29 +0100 Subject: [PATCH 2/8] Update GitHub workflow for v3.0.3 The GitHub Actions workflow has been updated to accommodate for the new version v3.0.3. Changes include adjusting the branch references and VERSION variable in the packages.yml file. --- .github/workflows/packages.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index c0c28fcfe..29f163d5c 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -3,7 +3,7 @@ on: workflow_dispatch: push: branches: - - v3.0.2 + - v3.0.3 release: types: [ prereleased, published ] env: @@ -18,10 +18,10 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 - - name: Verify commit exists in origin/v3.0.2 + - name: Verify commit exists in origin/v3.0.3 run: | git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/* - git branch --remote --contains | grep origin/v3.0.2 + git branch --remote --contains | grep origin/v3.0.3 - name: Set VERSION variable run: | if [[ "${{ github.ref }}" == refs/tags/* && "${{ github.event_name }}" == "release" && "${{ github.event.action }}" == "published" ]]; then @@ -29,7 +29,7 @@ jobs: TAG_NAME=${TAG_NAME#refs/tags/} # remove the refs/tags/ prefix echo "VERSION=${TAG_NAME}" >> $GITHUB_ENV else - echo "VERSION=3.0.2-preview.${{github.run_number}}" >> $GITHUB_ENV + echo "VERSION=3.0.3-preview.${{github.run_number}}" >> $GITHUB_ENV fi - name: Build run: dotnet build --configuration Release /p:Version=${VERSION} From 66d8e4b20fda9575a5736475a4752c9ad1f68ea2 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Fri, 12 Jan 2024 08:47:41 +0100 Subject: [PATCH 3/8] Updated MassTransit sample project This commit updates the Elsa.Samples.AspNet.MassTransitActivities.csproj --- Elsa.sln | 36 +++++------ src/bundles/Elsa.Server.Web/Program.cs | 3 +- src/bundles/Elsa.Server.Web/appsettings.json | 2 +- .../Elsa.ServerAndStudio.Web.csproj | 1 + .../Elsa.ServerAndStudio.Web/Program.cs | 59 +++++++++++-------- .../Elsa.ServerAndStudio.Web/appsettings.json | 3 +- ...amples.AspNet.MassTransitActivities.csproj | 2 + .../Program.cs | 22 +++++-- 8 files changed, 77 insertions(+), 51 deletions(-) diff --git a/Elsa.sln b/Elsa.sln index 458554229..493d4da73 100644 --- a/Elsa.sln +++ b/Elsa.sln @@ -20,7 +20,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution", "solution", "{7D packages.props = packages.props README.md = README.md update-migrations.sh = update-migrations.sh - frameworks.props = frameworks.props + frameworks.props = frameworks.props EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{0354F050-3992-4DD4-B0EE-5FBA04AC72B6}" @@ -253,47 +253,47 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.EntityFrameworkCore.My EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.EntityFrameworkCore.PostgreSql", "src\modules\Elsa.EntityFrameworkCore.PostgreSql\Elsa.EntityFrameworkCore.PostgreSql.csproj", "{84AB9951-3DBF-43A4-8F5D-AEED1102CE88}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Alterations.MassTransit", "src\modules\Elsa.Alterations.MassTransit\Elsa.Alterations.MassTransit.csproj", "{1F621382-08FB-45EA-B94C-96A7FECB9489}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Alterations.MassTransit", "src\modules\Elsa.Alterations.MassTransit\Elsa.Alterations.MassTransit.csproj", "{1F621382-08FB-45EA-B94C-96A7FECB9489}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Activities.UnitTests", "test\unit\Elsa.Activities.UnitTests\Elsa.Activities.UnitTests.csproj", "{E6562B0F-AF64-472A-B009-BF6D40DDE99B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Activities.UnitTests", "test\unit\Elsa.Activities.UnitTests\Elsa.Activities.UnitTests.csproj", "{E6562B0F-AF64-472A-B009-BF6D40DDE99B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.ServiceBus.IntegrationTests", "test\integration\Elsa.ServiceBus.IntegrationTests\Elsa.ServiceBus.IntegrationTests.csproj", "{9504E3F3-F77F-437A-8644-D23D7F5FCF8B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ElsaStudioWebAssembly", "src\bundles\ElsaStudioWebAssembly\ElsaStudioWebAssembly.csproj", "{E12A1BDF-5D65-493B-835D-AFBC480A5650}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ElsaStudioWebAssembly", "src\bundles\ElsaStudioWebAssembly\ElsaStudioWebAssembly.csproj", "{E12A1BDF-5D65-493B-835D-AFBC480A5650}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.EntityFrameworkCore.Common", "src\modules\Elsa.EntityFrameworkCore.Common\Elsa.EntityFrameworkCore.Common.csproj", "{FBA14F8A-9F14-4364-ABDB-B8AE81A0D755}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.EntityFrameworkCore.Common", "src\modules\Elsa.EntityFrameworkCore.Common\Elsa.EntityFrameworkCore.Common.csproj", "{FBA14F8A-9F14-4364-ABDB-B8AE81A0D755}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Quartz.EntityFrameworkCore.Sqlite", "src\modules\Elsa.Quartz.EntityFrameworkCore.Sqlite\Elsa.Quartz.EntityFrameworkCore.Sqlite.csproj", "{A71557F2-D5FB-4772-9391-F7D18A3B6C44}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Quartz.EntityFrameworkCore.Sqlite", "src\modules\Elsa.Quartz.EntityFrameworkCore.Sqlite\Elsa.Quartz.EntityFrameworkCore.Sqlite.csproj", "{A71557F2-D5FB-4772-9391-F7D18A3B6C44}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Quartz.EntityFrameworkCore.SqlServer", "src\modules\Elsa.Quartz.EntityFrameworkCore.SqlServer\Elsa.Quartz.EntityFrameworkCore.SqlServer.csproj", "{05F3B23E-CF28-467B-AD3C-595EA4ED6B96}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Quartz.EntityFrameworkCore.SqlServer", "src\modules\Elsa.Quartz.EntityFrameworkCore.SqlServer\Elsa.Quartz.EntityFrameworkCore.SqlServer.csproj", "{05F3B23E-CF28-467B-AD3C-595EA4ED6B96}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Quartz.EntityFrameworkCore.MySql", "src\modules\Elsa.Quartz.EntityFrameworkCore.MySql\Elsa.Quartz.EntityFrameworkCore.MySql.csproj", "{74ACD9D0-8B4C-42FA-A582-E93BF0075023}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Quartz.EntityFrameworkCore.MySql", "src\modules\Elsa.Quartz.EntityFrameworkCore.MySql\Elsa.Quartz.EntityFrameworkCore.MySql.csproj", "{74ACD9D0-8B4C-42FA-A582-E93BF0075023}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Quartz.EntityFrameworkCore.PostgreSql", "src\modules\Elsa.Quartz.EntityFrameworkCore.PostgreSql\Elsa.Quartz.EntityFrameworkCore.PostgreSql.csproj", "{CCCCEF8C-7D96-4BEA-B9D0-E91EDF08E65D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Quartz.EntityFrameworkCore.PostgreSql", "src\modules\Elsa.Quartz.EntityFrameworkCore.PostgreSql\Elsa.Quartz.EntityFrameworkCore.PostgreSql.csproj", "{CCCCEF8C-7D96-4BEA-B9D0-E91EDF08E65D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.FileStorage", "src\modules\Elsa.FileStorage\Elsa.FileStorage.csproj", "{732BF088-6AD7-4C4D-9A48-8074253596D4}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.FileStorage", "src\modules\Elsa.FileStorage\Elsa.FileStorage.csproj", "{732BF088-6AD7-4C4D-9A48-8074253596D4}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "storage", "storage", "{B818988E-639C-4E6E-85C1-B231BCAD9DAB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.CSharp", "src\modules\Elsa.CSharp\Elsa.CSharp.csproj", "{24331E82-D7AF-45B1-ACF0-CA6C3B0B77DC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.CSharp", "src\modules\Elsa.CSharp\Elsa.CSharp.csproj", "{24331E82-D7AF-45B1-ACF0-CA6C3B0B77DC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Python", "src\modules\Elsa.Python\Elsa.Python.csproj", "{790E94F2-5393-47DF-AC52-D9247F5B243A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Python", "src\modules\Elsa.Python\Elsa.Python.csproj", "{790E94F2-5393-47DF-AC52-D9247F5B243A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.MassTransit.RabbitMq", "src\modules\Elsa.MassTransit.RabbitMq\Elsa.MassTransit.RabbitMq.csproj", "{169BEA3D-2A81-47EE-A6C1-3F8719EEC1F6}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.MassTransit.RabbitMq", "src\modules\Elsa.MassTransit.RabbitMq\Elsa.MassTransit.RabbitMq.csproj", "{169BEA3D-2A81-47EE-A6C1-3F8719EEC1F6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.MassTransit.AzureServiceBus", "src\modules\Elsa.MassTransit.AzureServiceBus\Elsa.MassTransit.AzureServiceBus.csproj", "{5B1AF00E-1030-4BBA-9C1A-1DC5AEFDD44A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.MassTransit.AzureServiceBus", "src\modules\Elsa.MassTransit.AzureServiceBus\Elsa.MassTransit.AzureServiceBus.csproj", "{5B1AF00E-1030-4BBA-9C1A-1DC5AEFDD44A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.AspNet.Heartbeats", "src\samples\aspnet\Elsa.Samples.AspNet.Heartbeats\Elsa.Samples.AspNet.Heartbeats.csproj", "{26888832-DBEA-4B23-8DC2-84478A702CC4}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.AspNet.Heartbeats", "src\samples\aspnet\Elsa.Samples.AspNet.Heartbeats\Elsa.Samples.AspNet.Heartbeats.csproj", "{26888832-DBEA-4B23-8DC2-84478A702CC4}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pipelines", "pipelines", "{B789B743-0FBE-4BBC-9F45-84C20C8D4814}" ProjectSection(SolutionItems) = preProject .github\workflows\elsa-server-and-studio.yml = .github\workflows\elsa-server-and-studio.yml .github\workflows\elsa-server.yml = .github\workflows\elsa-server.yml - .github\workflows\packages.yml = .github\workflows\packages.yml + .github\workflows\packages.yml = .github\workflows\packages.yml .github\workflows\elsa-studio.yml = .github\workflows\elsa-studio.yml EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Studio.Web", "src\bundles\Elsa.Studio.Web\Elsa.Studio.Web.csproj", "{D5C149EE-276C-4C59-98F9-37F0EA2A7866}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Studio.Web", "src\bundles\Elsa.Studio.Web\Elsa.Studio.Web.csproj", "{D5C149EE-276C-4C59-98F9-37F0EA2A7866}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.AspNet.CustomUIHandler", "src\samples\aspnet\Elsa.Samples.AspNet.CustomUIHandler\Elsa.Samples.AspNet.CustomUIHandler.csproj", "{832D6FF5-16D3-41D1-8FDD-D9BEC26BDA6A}" EndProject @@ -864,7 +864,7 @@ Global {05F3B23E-CF28-467B-AD3C-595EA4ED6B96} = {AB797AF0-C12C-46DE-A157-7E25625C6200} {74ACD9D0-8B4C-42FA-A582-E93BF0075023} = {AB797AF0-C12C-46DE-A157-7E25625C6200} {CCCCEF8C-7D96-4BEA-B9D0-E91EDF08E65D} = {AB797AF0-C12C-46DE-A157-7E25625C6200} - {B818988E-639C-4E6E-85C1-B231BCAD9DAB} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} + {B818988E-639C-4E6E-85C1-B231BCAD9DAB} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} {732BF088-6AD7-4C4D-9A48-8074253596D4} = {B818988E-639C-4E6E-85C1-B231BCAD9DAB} {24331E82-D7AF-45B1-ACF0-CA6C3B0B77DC} = {6EF07978-A6D2-40EB-891D-7D70C5F37E76} {790E94F2-5393-47DF-AC52-D9247F5B243A} = {6EF07978-A6D2-40EB-891D-7D70C5F37E76} diff --git a/src/bundles/Elsa.Server.Web/Program.cs b/src/bundles/Elsa.Server.Web/Program.cs index 7df6fea32..89ee7b6b3 100644 --- a/src/bundles/Elsa.Server.Web/Program.cs +++ b/src/bundles/Elsa.Server.Web/Program.cs @@ -10,7 +10,6 @@ using Elsa.EntityFrameworkCore.Modules.Identity; using Elsa.EntityFrameworkCore.Modules.Management; using Elsa.EntityFrameworkCore.Modules.Runtime; using Elsa.Extensions; -using Elsa.Http.Handlers; using Elsa.Http.Options; using Elsa.MongoDb.Extensions; using Elsa.MongoDb.Modules.Identity; @@ -29,7 +28,7 @@ const bool useHangfire = false; const bool useQuartz = true; const bool useMassTransit = true; const bool useMassTransitAzureServiceBus = false; -const bool useMassTransitRabbitMq = false; +const bool useMassTransitRabbitMq = true; var builder = WebApplication.CreateBuilder(args); var services = builder.Services; diff --git a/src/bundles/Elsa.Server.Web/appsettings.json b/src/bundles/Elsa.Server.Web/appsettings.json index 9859fc4f8..131ccbe59 100644 --- a/src/bundles/Elsa.Server.Web/appsettings.json +++ b/src/bundles/Elsa.Server.Web/appsettings.json @@ -17,7 +17,7 @@ "Sqlite": "Data Source=App_Data/elsa.sqlite.db;Cache=Shared;", "MongoDb": "mongodb://localhost:27017/elsa-workflows", "AzureServiceBus": "", - "RabbitMq": "amqp://guest:guest@localhost:5672/elsa" + "RabbitMq": "amqp://guest:guest@localhost:5672" }, "Smtp": { "Host": "localhost", diff --git a/src/bundles/Elsa.ServerAndStudio.Web/Elsa.ServerAndStudio.Web.csproj b/src/bundles/Elsa.ServerAndStudio.Web/Elsa.ServerAndStudio.Web.csproj index 40a7047bc..659bc16ef 100644 --- a/src/bundles/Elsa.ServerAndStudio.Web/Elsa.ServerAndStudio.Web.csproj +++ b/src/bundles/Elsa.ServerAndStudio.Web/Elsa.ServerAndStudio.Web.csproj @@ -18,6 +18,7 @@ + diff --git a/src/bundles/Elsa.ServerAndStudio.Web/Program.cs b/src/bundles/Elsa.ServerAndStudio.Web/Program.cs index eb19d40ac..3726828da 100644 --- a/src/bundles/Elsa.ServerAndStudio.Web/Program.cs +++ b/src/bundles/Elsa.ServerAndStudio.Web/Program.cs @@ -6,6 +6,8 @@ using Elsa.Extensions; using Elsa.Webhooks.Extensions; using Microsoft.AspNetCore.Mvc; +const bool useMassTransit = true; + var builder = WebApplication.CreateBuilder(args); builder.WebHost.UseStaticWebAssets(); var services = builder.Services; @@ -16,32 +18,39 @@ var identityTokenSection = identitySection.GetSection("Tokens"); // Add Elsa services. services - .AddElsa(elsa => elsa - .UseSasTokens() - .UseIdentity(identity => + .AddElsa(elsa => + { + elsa + .UseSasTokens() + .UseIdentity(identity => + { + identity.IdentityOptions = options => identitySection.Bind(options); + identity.TokenOptions = options => identityTokenSection.Bind(options); + identity.UseConfigurationBasedUserProvider(options => identitySection.Bind(options)); + identity.UseConfigurationBasedApplicationProvider(options => identitySection.Bind(options)); + identity.UseConfigurationBasedRoleProvider(options => identitySection.Bind(options)); + }) + .UseDefaultAuthentication() + .UseWorkflowManagement(management => management.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString))) + .UseWorkflowRuntime(runtime => runtime.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString))) + .UseScheduling() + .UseJavaScript(options => options.AllowClrAccess = true) + .UseLiquid() + .UseCSharp() + .UsePython() + .UseHttp(http => http.ConfigureHttpOptions = options => configuration.GetSection("Http").Bind(options)) + .UseEmail(email => email.ConfigureOptions = options => configuration.GetSection("Smtp").Bind(options)) + .UseWebhooks(webhooks => webhooks.WebhookOptions = options => builder.Configuration.GetSection("Webhooks").Bind(options)) + .UseWorkflowsApi() + .UseRealTimeWorkflows() + .AddActivitiesFrom() + .AddWorkflowsFrom(); + + if (useMassTransit) { - identity.IdentityOptions = options => identitySection.Bind(options); - identity.TokenOptions = options => identityTokenSection.Bind(options); - identity.UseConfigurationBasedUserProvider(options => identitySection.Bind(options)); - identity.UseConfigurationBasedApplicationProvider(options => identitySection.Bind(options)); - identity.UseConfigurationBasedRoleProvider(options => identitySection.Bind(options)); - }) - .UseDefaultAuthentication() - .UseWorkflowManagement(management => management.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString))) - .UseWorkflowRuntime(runtime => runtime.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString))) - .UseScheduling() - .UseJavaScript(options => options.AllowClrAccess = true) - .UseLiquid() - .UseCSharp() - .UsePython() - .UseHttp(http => http.ConfigureHttpOptions = options => configuration.GetSection("Http").Bind(options)) - .UseEmail(email => email.ConfigureOptions = options => configuration.GetSection("Smtp").Bind(options)) - .UseWebhooks(webhooks => webhooks.WebhookOptions = options => builder.Configuration.GetSection("Webhooks").Bind(options)) - .UseWorkflowsApi() - .UseRealTimeWorkflows() - .AddActivitiesFrom() - .AddWorkflowsFrom() - ); + elsa.UseMassTransit(); + } + }); services.AddHealthChecks(); diff --git a/src/bundles/Elsa.ServerAndStudio.Web/appsettings.json b/src/bundles/Elsa.ServerAndStudio.Web/appsettings.json index 6a427b4da..4f0c9d1bc 100644 --- a/src/bundles/Elsa.ServerAndStudio.Web/appsettings.json +++ b/src/bundles/Elsa.ServerAndStudio.Web/appsettings.json @@ -13,7 +13,8 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - "Sqlite": "Data Source=elsa.sqlite.db;Cache=Shared;" + "Sqlite": "Data Source=elsa.sqlite.db;Cache=Shared;", + "RabbitMq": "rabbitmq://guest:guest@localhost:5672" }, "Hosting": { "BasePath": "" diff --git a/src/samples/aspnet/Elsa.Samples.AspNet.MassTransitActivities/Elsa.Samples.AspNet.MassTransitActivities.csproj b/src/samples/aspnet/Elsa.Samples.AspNet.MassTransitActivities/Elsa.Samples.AspNet.MassTransitActivities.csproj index 6406236ea..00da2f741 100644 --- a/src/samples/aspnet/Elsa.Samples.AspNet.MassTransitActivities/Elsa.Samples.AspNet.MassTransitActivities.csproj +++ b/src/samples/aspnet/Elsa.Samples.AspNet.MassTransitActivities/Elsa.Samples.AspNet.MassTransitActivities.csproj @@ -8,6 +8,8 @@ + + diff --git a/src/samples/aspnet/Elsa.Samples.AspNet.MassTransitActivities/Program.cs b/src/samples/aspnet/Elsa.Samples.AspNet.MassTransitActivities/Program.cs index b68fa11ab..efc6b8bc6 100644 --- a/src/samples/aspnet/Elsa.Samples.AspNet.MassTransitActivities/Program.cs +++ b/src/samples/aspnet/Elsa.Samples.AspNet.MassTransitActivities/Program.cs @@ -28,9 +28,23 @@ builder.Services.AddElsa(elsa => // Add services for HTTP activities and workflow middleware. elsa.UseHttp(); + + // Use C#. + elsa.UseCSharp(options => + { + options.Assemblies.Add(typeof(OrderCreated).Assembly); + options.Namespaces.Add(typeof(OrderCreated).Namespace!); + }); - // Use JavaScript and Liquid. - elsa.UseJavaScript(); + // Use JavaScript. + elsa.UseJavaScript(options => + { + options.AllowClrAccess = true; + options.RegisterType(); + options.RegisterType(); + }); + + // Use Liquid. elsa.UseLiquid(); // Configure identity so that we can create a default admin user. @@ -39,7 +53,7 @@ builder.Services.AddElsa(elsa => identity.UseAdminUserProvider(); identity.TokenOptions = options => { - options.SigningKey = "secret-token-signing-key"; + options.SigningKey = "super-secret-and-securely-stored-token-signing-key"; options.AccessTokenLifetime = TimeSpan.FromDays(1); }; }); @@ -50,7 +64,7 @@ builder.Services.AddElsa(elsa => // Configure MassTransit. elsa.UseMassTransit(massTransit => { - massTransit.UseRabbitMq(rabbitMqConnectionString); + //massTransit.UseRabbitMq(rabbitMqConnectionString); massTransit.AddMessageType(); massTransit.AddMessageType(); }); From ac9428a6e0ed6fbdc63e29514f05cb924fc165a9 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Mon, 15 Jan 2024 21:15:05 +0100 Subject: [PATCH 4/8] Allow creation of variables dynamically via `setVariable` (#4800) * Disable MassTransitRabbitMq in Elsa.Server.Web. * Create variable if not exists in Workflow.Core The update introduced checks if a variable exists before attempting to set its value in the ExpressionExecutionContextExtensions. If the variable doesn't exist, it now creates one automatically. Fixes #4789 * Remove unnecessary comment The comment indicating to create a variable if it doesn't exist was deemed superfluous and removed from the ExpressionExecutionContextExtensions.cs file. This improves code cleanliness as the functionality is self-explanatory through the existing code structure. --- src/bundles/Elsa.Server.Web/Program.cs | 2 +- .../Extensions/ExpressionExecutionContextExtensions.cs | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/bundles/Elsa.Server.Web/Program.cs b/src/bundles/Elsa.Server.Web/Program.cs index 89ee7b6b3..1c35e86c8 100644 --- a/src/bundles/Elsa.Server.Web/Program.cs +++ b/src/bundles/Elsa.Server.Web/Program.cs @@ -28,7 +28,7 @@ const bool useHangfire = false; const bool useQuartz = true; const bool useMassTransit = true; const bool useMassTransitAzureServiceBus = false; -const bool useMassTransitRabbitMq = true; +const bool useMassTransitRabbitMq = false; var builder = WebApplication.CreateBuilder(args); var services = builder.Services; diff --git a/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs b/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs index cb9dd853c..b93272793 100644 --- a/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs +++ b/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs @@ -292,7 +292,12 @@ public static class ExpressionExecutionContextExtensions select v; var variable = q.FirstOrDefault(); - variable?.Set(context, value); + + if(variable != null) + variable.Set(context, value); + + if (variable == null) + CreateVariable(context, variableName, value); } /// From a7851175b81d75ba48046a3f756fc07a85c9f440 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Tue, 23 Jan 2024 21:58:38 +0100 Subject: [PATCH 5/8] Add input application to workflow state extractor A new method ApplyInput has been added to prevent overwriting any existing input in the WorkflowExecutionContext. Now, input items are added to the workflow execution context only if they don't exist there already. The Apply method has been updated as well to add workflow state inputs appropriately. Fixes #4705 --- .../Services/WorkflowStateExtractor.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/modules/Elsa.Workflows.Core/Services/WorkflowStateExtractor.cs b/src/modules/Elsa.Workflows.Core/Services/WorkflowStateExtractor.cs index aa8ef62da..347f7f703 100644 --- a/src/modules/Elsa.Workflows.Core/Services/WorkflowStateExtractor.cs +++ b/src/modules/Elsa.Workflows.Core/Services/WorkflowStateExtractor.cs @@ -35,6 +35,13 @@ public class WorkflowStateExtractor : IWorkflowStateExtractor return state; } + + private void ApplyInput(WorkflowState state, WorkflowExecutionContext workflowExecutionContext) + { + // Only add input from state if the input doesn't already exist on the workflow execution context. + foreach (var inputItem in state.Input) + if (!workflowExecutionContext.Input.ContainsKey(inputItem.Key)) workflowExecutionContext.Input.Add(inputItem.Key, inputItem.Value); + } private IDictionary GetPersistableInput(WorkflowExecutionContext workflowExecutionContext) { @@ -55,7 +62,6 @@ public class WorkflowStateExtractor : IWorkflowStateExtractor /// public WorkflowExecutionContext Apply(WorkflowExecutionContext workflowExecutionContext, WorkflowState state) { - // Do not map input. We don't want to overwrite the input that was passed to the workflow. workflowExecutionContext.Id = state.Id; workflowExecutionContext.CorrelationId = state.CorrelationId; workflowExecutionContext.SubStatus = state.SubStatus; @@ -63,6 +69,7 @@ public class WorkflowStateExtractor : IWorkflowStateExtractor workflowExecutionContext.Output = state.Output; workflowExecutionContext.ExecutionLogSequence = state.ExecutionLogSequence; workflowExecutionContext.CreatedAt = state.CreatedAt; + ApplyInput(state, workflowExecutionContext); ApplyProperties(state, workflowExecutionContext); ApplyActivityExecutionContexts(state, workflowExecutionContext); ApplyCompletionCallbacks(state, workflowExecutionContext); From a1b7afdf4fed9df4bd9461d96f1df2545f3181da Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Tue, 23 Jan 2024 22:01:13 +0100 Subject: [PATCH 6/8] Reorder methods in WorkflowStateExtractor service The private methods within the WorkflowStateExtractor service have been reordered for readability and maintainability. The `ApplyInput` and `GetPersistableInput` methods have been moved to a position just before the `ExtractProperties` method. This ensures that similar or related methods are grouped together, improving the logical structure of the code. --- .../Services/WorkflowStateExtractor.cs | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/modules/Elsa.Workflows.Core/Services/WorkflowStateExtractor.cs b/src/modules/Elsa.Workflows.Core/Services/WorkflowStateExtractor.cs index 347f7f703..3a6ce6851 100644 --- a/src/modules/Elsa.Workflows.Core/Services/WorkflowStateExtractor.cs +++ b/src/modules/Elsa.Workflows.Core/Services/WorkflowStateExtractor.cs @@ -35,6 +35,24 @@ public class WorkflowStateExtractor : IWorkflowStateExtractor return state; } + + /// + public WorkflowExecutionContext Apply(WorkflowExecutionContext workflowExecutionContext, WorkflowState state) + { + workflowExecutionContext.Id = state.Id; + workflowExecutionContext.CorrelationId = state.CorrelationId; + workflowExecutionContext.SubStatus = state.SubStatus; + workflowExecutionContext.Bookmarks = state.Bookmarks; + workflowExecutionContext.Output = state.Output; + workflowExecutionContext.ExecutionLogSequence = state.ExecutionLogSequence; + workflowExecutionContext.CreatedAt = state.CreatedAt; + ApplyInput(state, workflowExecutionContext); + ApplyProperties(state, workflowExecutionContext); + ApplyActivityExecutionContexts(state, workflowExecutionContext); + ApplyCompletionCallbacks(state, workflowExecutionContext); + ApplyScheduledActivities(state, workflowExecutionContext); + return workflowExecutionContext; + } private void ApplyInput(WorkflowState state, WorkflowExecutionContext workflowExecutionContext) { @@ -59,24 +77,6 @@ public class WorkflowStateExtractor : IWorkflowStateExtractor return filteredInput; } - /// - public WorkflowExecutionContext Apply(WorkflowExecutionContext workflowExecutionContext, WorkflowState state) - { - workflowExecutionContext.Id = state.Id; - workflowExecutionContext.CorrelationId = state.CorrelationId; - workflowExecutionContext.SubStatus = state.SubStatus; - workflowExecutionContext.Bookmarks = state.Bookmarks; - workflowExecutionContext.Output = state.Output; - workflowExecutionContext.ExecutionLogSequence = state.ExecutionLogSequence; - workflowExecutionContext.CreatedAt = state.CreatedAt; - ApplyInput(state, workflowExecutionContext); - ApplyProperties(state, workflowExecutionContext); - ApplyActivityExecutionContexts(state, workflowExecutionContext); - ApplyCompletionCallbacks(state, workflowExecutionContext); - ApplyScheduledActivities(state, workflowExecutionContext); - return workflowExecutionContext; - } - private void ExtractProperties(WorkflowState state, WorkflowExecutionContext workflowExecutionContext) { state.Properties = workflowExecutionContext.Properties; From 792c06ee04a5558456bec8cba5e17fb528f37962 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 24 Jan 2024 01:18:00 +0100 Subject: [PATCH 7/8] Update GitHub actions workflow to target v3.0.4 The GitHub actions workflow has been updated to target the version branch v3.0.4. The necessary checks and commands have been modified accordingly to ensure proper compatibility with the new branch. This update is necessary for the correct functioning of the automatic deployment activities. --- .github/workflows/packages.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 29f163d5c..72d1388c2 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -3,7 +3,7 @@ on: workflow_dispatch: push: branches: - - v3.0.3 + - v3.0.4 release: types: [ prereleased, published ] env: @@ -18,10 +18,10 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 - - name: Verify commit exists in origin/v3.0.3 + - name: Verify commit exists in origin/v3.0.4 run: | git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/* - git branch --remote --contains | grep origin/v3.0.3 + git branch --remote --contains | grep origin/v3.0.4 - name: Set VERSION variable run: | if [[ "${{ github.ref }}" == refs/tags/* && "${{ github.event_name }}" == "release" && "${{ github.event.action }}" == "published" ]]; then From 03743d6da131fd1c4d1e5c72c07a8f1416868aea Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 24 Jan 2024 01:21:52 +0100 Subject: [PATCH 8/8] Update version number in GitHub workflow The version number has been updated in the GitHub actions workflow file. Previously, it was hardcoded to "3.0.3-preview", but now it's switched to "3.0.4-preview". This change keeps our software versioning consistent and up-to-date. --- .github/workflows/packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 72d1388c2..bb54e11bd 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -29,7 +29,7 @@ jobs: TAG_NAME=${TAG_NAME#refs/tags/} # remove the refs/tags/ prefix echo "VERSION=${TAG_NAME}" >> $GITHUB_ENV else - echo "VERSION=3.0.3-preview.${{github.run_number}}" >> $GITHUB_ENV + echo "VERSION=3.0.4-preview.${{github.run_number}}" >> $GITHUB_ENV fi - name: Build run: dotnet build --configuration Release /p:Version=${VERSION}