diff --git a/src/bundles/Elsa.WorkflowServer.Web/Elsa.WorkflowServer.Web.csproj b/src/bundles/Elsa.WorkflowServer.Web/Elsa.WorkflowServer.Web.csproj index be0b00213..3f6bf4503 100644 --- a/src/bundles/Elsa.WorkflowServer.Web/Elsa.WorkflowServer.Web.csproj +++ b/src/bundles/Elsa.WorkflowServer.Web/Elsa.WorkflowServer.Web.csproj @@ -9,6 +9,7 @@ + @@ -34,6 +35,7 @@ + diff --git a/src/bundles/Elsa.WorkflowServer.Web/Program.cs b/src/bundles/Elsa.WorkflowServer.Web/Program.cs index 830b1d970..e6a06c5b8 100644 --- a/src/bundles/Elsa.WorkflowServer.Web/Program.cs +++ b/src/bundles/Elsa.WorkflowServer.Web/Program.cs @@ -1,3 +1,4 @@ +using Elsa.EntityFrameworkCore.Extensions; using Elsa.EntityFrameworkCore.Modules.Identity; using Elsa.EntityFrameworkCore.Modules.Management; using Elsa.EntityFrameworkCore.Modules.Runtime; @@ -10,9 +11,11 @@ using Elsa.MongoDb.Modules.Runtime; using Elsa.WorkflowServer.Web; using Microsoft.Data.Sqlite; using Proto.Persistence.Sqlite; +using Proto.Persistence.SqlServer; const bool useMongoDb = false; -const bool useProtoActor = false; +const bool useSqlServer = true; +const bool useProtoActor = true; const bool useHangfire = false; var builder = WebApplication.CreateBuilder(args); @@ -21,6 +24,7 @@ var configuration = builder.Configuration; var identitySection = configuration.GetSection("Identity"); var identityTokenSection = identitySection.GetSection("Tokens"); var sqliteConnectionString = configuration.GetConnectionString("Sqlite"); +var sqlServerConnectionString = configuration.GetConnectionString("SqlServer"); var mongoDbConnectionString = configuration.GetConnectionString("MongoDb")!; // Add Elsa services. @@ -43,7 +47,13 @@ services if(useMongoDb) identity.UseMongoDb(); else - identity.UseEntityFrameworkCore(); + identity.UseEntityFrameworkCore(ef => + { + if(useSqlServer) + ef.UseSqlServer(sqlServerConnectionString!); + else + ef.UseSqlite(sqliteConnectionString); + }); identity.IdentityOptions = options => identitySection.Bind(options); identity.TokenOptions = options => identityTokenSection.Bind(options); @@ -57,7 +67,13 @@ services if(useMongoDb) management.UseMongoDb(); else - management.UseEntityFrameworkCore(); + management.UseEntityFrameworkCore(ef => + { + if(useSqlServer) + ef.UseSqlServer(sqlServerConnectionString!); + else + ef.UseSqlite(sqliteConnectionString); + }); management.AddVariableType>("Api"); management.AddVariableType("Api"); @@ -68,17 +84,37 @@ services if(useMongoDb) runtime.UseMongoDb(); else - runtime.UseEntityFrameworkCore(); + runtime.UseEntityFrameworkCore(ef => + { + if(useSqlServer) + ef.UseSqlServer(sqlServerConnectionString!); + else + ef.UseSqlite(sqliteConnectionString); + }); if(useProtoActor) - runtime.UseProtoActor(proto => proto.PersistenceProvider = _ => new SqliteProvider(new SqliteConnectionStringBuilder(sqliteConnectionString))); + { + runtime.UseProtoActor(proto => proto.PersistenceProvider = _ => + { + if(useSqlServer) + return new SqlServerProvider(sqlServerConnectionString!, true, "", "proto_actor"); + else + return new SqliteProvider(new SqliteConnectionStringBuilder(sqliteConnectionString)); + }); + } else runtime.UseDefaultRuntime(dr => { if(useMongoDb) dr.UseMongoDb(); else - dr.UseEntityFrameworkCore(); + dr.UseEntityFrameworkCore(ef => + { + if(useSqlServer) + ef.UseSqlServer(sqlServerConnectionString!); + else + ef.UseSqlite(sqliteConnectionString); + }); }); runtime.UseExecutionLogRecords(e => @@ -86,7 +122,13 @@ services if(useMongoDb) e.UseMongoDb(); else - e.UseEntityFrameworkCore(); + e.UseEntityFrameworkCore(ef => + { + if(useSqlServer) + ef.UseSqlServer(sqlServerConnectionString!); + else + ef.UseSqlite(sqliteConnectionString); + }); }); runtime.UseMassTransitDispatcher(); diff --git a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Modules/Runtime/Extensions.cs b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Modules/Runtime/Extensions.cs index 4569c45d3..268e3ac7e 100644 --- a/src/modules/Elsa.EntityFrameworkCore.SqlServer/Modules/Runtime/Extensions.cs +++ b/src/modules/Elsa.EntityFrameworkCore.SqlServer/Modules/Runtime/Extensions.cs @@ -6,6 +6,12 @@ namespace Elsa.EntityFrameworkCore.Extensions; public static partial class Extensions { + public static EFCoreWorkflowRuntimePersistenceFeature UseSqlServer(this EFCoreWorkflowRuntimePersistenceFeature feature, string connectionString, ElsaDbContextOptions? options = default) + { + feature.DbContextOptionsBuilder = (_, db) => db.UseElsaSqlServer(connectionString, options); + return feature; + } + public static EFCoreDefaultWorkflowRuntimePersistenceFeature UseSqlServer(this EFCoreDefaultWorkflowRuntimePersistenceFeature feature, string connectionString, ElsaDbContextOptions? options = default) { feature.DbContextOptionsBuilder = (_, db) => db.UseElsaSqlServer(connectionString, options); diff --git a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Modules/Runtime/Extensions.cs b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Modules/Runtime/Extensions.cs index f09a371f1..6cd791f83 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Sqlite/Modules/Runtime/Extensions.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Sqlite/Modules/Runtime/Extensions.cs @@ -11,8 +11,8 @@ public static partial class Extensions { feature.DbContextOptionsBuilder = (_, db) => db.UseElsaSqlite(connectionString, options); return feature; - } + public static EFCoreDefaultWorkflowRuntimePersistenceFeature UseSqlite(this EFCoreDefaultWorkflowRuntimePersistenceFeature feature, string connectionString = Constants.DefaultConnectionString, ElsaDbContextOptions? options = default) { feature.DbContextOptionsBuilder = (_, db) => db.UseElsaSqlite(connectionString, options); diff --git a/src/modules/Elsa.ProtoActor/Elsa.ProtoActor.csproj b/src/modules/Elsa.ProtoActor/Elsa.ProtoActor.csproj index 0f0bdc5d0..f14653f74 100644 --- a/src/modules/Elsa.ProtoActor/Elsa.ProtoActor.csproj +++ b/src/modules/Elsa.ProtoActor/Elsa.ProtoActor.csproj @@ -1,7 +1,7 @@ - - + + net6.0;net7.0 @@ -12,31 +12,35 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - - - - - + + + + + + - - + + - - - + + + + + + + diff --git a/src/modules/Elsa.ProtoActor/Extensions/ClusterExtensions.cs b/src/modules/Elsa.ProtoActor/Extensions/ClusterExtensions.cs index 2613d3fdc..b13bcf4a2 100644 --- a/src/modules/Elsa.ProtoActor/Extensions/ClusterExtensions.cs +++ b/src/modules/Elsa.ProtoActor/Extensions/ClusterExtensions.cs @@ -1,5 +1,5 @@ using Elsa.ProtoActor.Grains; -using Elsa.ProtoActor.Protos; +using Elsa.ProtoActor.ProtoBuf; using Proto.Cluster; // ReSharper disable once CheckNamespace @@ -7,6 +7,6 @@ namespace Elsa.Extensions; internal static class ClusterExtensions { - public static RunningWorkflowsGrainClient GetNamedRunningWorkflowsGrain(this Cluster cluster) => cluster.GetRunningWorkflowsGrain(nameof(RunningWorkflowsGrain)); - public static WorkflowGrainClient GetNamedWorkflowGrain(this Cluster cluster, string workflowInstanceId) => cluster.GetWorkflowGrain($"{nameof(WorkflowGrain)}-{workflowInstanceId}"); + public static RunningWorkflowsClient GetNamedRunningWorkflowsGrain(this Cluster cluster) => cluster.GetRunningWorkflows(nameof(RunningWorkflows)); + public static WorkflowInstanceClient GetNamedWorkflowGrain(this Cluster cluster, string workflowInstanceId) => cluster.GetWorkflowInstance($"{nameof(WorkflowInstance)}-{workflowInstanceId}"); } \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor/Extensions/ProtoInputExtensions.cs b/src/modules/Elsa.ProtoActor/Extensions/ProtoInputExtensions.cs index abdfb3a32..2c85267f7 100644 --- a/src/modules/Elsa.ProtoActor/Extensions/ProtoInputExtensions.cs +++ b/src/modules/Elsa.ProtoActor/Extensions/ProtoInputExtensions.cs @@ -1,5 +1,5 @@ using System.Text.Json; -using Elsa.ProtoActor.Protos; +using Elsa.ProtoActor.ProtoBuf; using Elsa.Workflows.Core.Serialization.Converters; namespace Elsa.ProtoActor.Extensions; diff --git a/src/modules/Elsa.ProtoActor/Features/ProtoActorFeature.cs b/src/modules/Elsa.ProtoActor/Features/ProtoActorFeature.cs index 9294788cc..b9f0278e8 100644 --- a/src/modules/Elsa.ProtoActor/Features/ProtoActorFeature.cs +++ b/src/modules/Elsa.ProtoActor/Features/ProtoActorFeature.cs @@ -5,7 +5,7 @@ using Elsa.Features.Services; using Elsa.ProtoActor.Grains; using Elsa.ProtoActor.HostedServices; using Elsa.ProtoActor.Mappers; -using Elsa.ProtoActor.Protos; +using Elsa.ProtoActor.ProtoBuf; using Elsa.ProtoActor.Services; using Elsa.Workflows.Core.Features; using Elsa.Workflows.Runtime.Features; @@ -95,8 +95,8 @@ public class ProtoActorFeature : FeatureBase var clusterProvider = ClusterProvider(sp); var system = new ActorSystem(systemConfig).WithServiceProvider(sp); - var workflowGrainProps = system.DI().PropsFor(); - var workflowRegistryGrainProps = system.DI().PropsFor(); + var workflowGrainProps = system.DI().PropsFor(); + var workflowRegistryGrainProps = system.DI().PropsFor(); var clusterConfig = ClusterConfig .Setup(ClusterName, clusterProvider, new PartitionIdentityLookup()) @@ -104,8 +104,8 @@ public class ProtoActorFeature : FeatureBase .WithActorRequestTimeout(TimeSpan.FromHours(1)) .WithActorActivationTimeout(TimeSpan.FromHours(1)) .WithActorSpawnVerificationTimeout(TimeSpan.FromHours(1)) - .WithClusterKind(WorkflowGrainActor.Kind, workflowGrainProps) - .WithClusterKind(RunningWorkflowsGrainActor.Kind, workflowRegistryGrainProps) + .WithClusterKind(WorkflowInstanceActor.Kind, workflowGrainProps) + .WithClusterKind(RunningWorkflowsActor.Kind, workflowRegistryGrainProps) ; ActorSystemConfig(sp, systemConfig); @@ -143,8 +143,8 @@ public class ProtoActorFeature : FeatureBase // Actors. services - .AddTransient(sp => new WorkflowGrainActor((context, _) => ActivatorUtilities.CreateInstance(sp, context))) - .AddTransient(sp => new RunningWorkflowsGrainActor((context, _) => ActivatorUtilities.CreateInstance(sp, context))) + .AddTransient(sp => new WorkflowInstanceActor((context, _) => ActivatorUtilities.CreateInstance(sp, context))) + .AddTransient(sp => new RunningWorkflowsActor((context, _) => ActivatorUtilities.CreateInstance(sp, context))) ; } @@ -154,6 +154,6 @@ public class ProtoActorFeature : FeatureBase private static GrpcNetRemoteConfig CreateDefaultRemoteConfig(IServiceProvider serviceProvider) => GrpcNetRemoteConfig.BindToLocalhost() - .WithProtoMessages(MessagesReflection.Descriptor) + .WithProtoMessages(SharedReflection.Descriptor) .WithProtoMessages(EmptyReflection.Descriptor); } \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor/Grains/RunningWorkflowsGrain.cs b/src/modules/Elsa.ProtoActor/Grains/RunningWorkflows.cs similarity index 76% rename from src/modules/Elsa.ProtoActor/Grains/RunningWorkflowsGrain.cs rename to src/modules/Elsa.ProtoActor/Grains/RunningWorkflows.cs index 6dc887b1a..966b7de9e 100644 --- a/src/modules/Elsa.ProtoActor/Grains/RunningWorkflowsGrain.cs +++ b/src/modules/Elsa.ProtoActor/Grains/RunningWorkflows.cs @@ -1,5 +1,6 @@ using Elsa.ProtoActor.Extensions; -using Elsa.ProtoActor.Protos; +using Elsa.ProtoActor.Models; +using Elsa.ProtoActor.ProtoBuf; using Proto; using Proto.Cluster; using Proto.Persistence; @@ -7,19 +8,18 @@ using Proto.Persistence.SnapshotStrategies; namespace Elsa.ProtoActor.Grains; -// TODO: Replace this grain with a store-based implementation that stores metrics. /// /// Represents a registry of workflow instances for a given workflow definition version. /// -public class RunningWorkflowsGrain : RunningWorkflowsGrainBase +public class RunningWorkflows : RunningWorkflowsBase { - private const int EventsPerSnapshot = 100; + private const int EventsPerSnapshot = 1; private readonly Persistence _persistence; - private IDictionary _lookupByInstanceId = new Dictionary(); - private IDictionary _lookupByCorrelationId = new Dictionary(); + private IDictionary _lookupByInstanceId = new Dictionary(); + private IDictionary _lookupByCorrelationId = new Dictionary(); /// - public RunningWorkflowsGrain(IProvider provider, IContext context) : base(context) + public RunningWorkflows(IProvider provider, IContext context) : base(context) { _persistence = Persistence.WithEventSourcingAndSnapshotting( provider, @@ -31,6 +31,12 @@ public class RunningWorkflowsGrain : RunningWorkflowsGrainBase GetState); } + /// + public override async Task OnStarted() + { + await _persistence.RecoverStateAsync(); + } + /// public override async Task Register(RegisterRunningWorkflowRequest request) => await _persistence.PersistRollingEventAsync(request, EventsPerSnapshot); @@ -58,7 +64,7 @@ public class RunningWorkflowsGrain : RunningWorkflowsGrainBase private void ApplySnapshot(Snapshot snapshot) { - var registrySnapshot = (WorkflowRegistrySnapshot)snapshot.State; + var registrySnapshot = (RunningWorkflowsSnapshot)snapshot.State; _lookupByCorrelationId = registrySnapshot.Entries.Where(x => !string.IsNullOrEmpty(x.CorrelationId)).ToDictionary(x => x.CorrelationId!); _lookupByInstanceId = registrySnapshot.Entries.ToDictionary(x => x.InstanceId); } @@ -76,11 +82,11 @@ public class RunningWorkflowsGrain : RunningWorkflowsGrainBase } } - private object GetState() => new WorkflowRegistrySnapshot(_lookupByInstanceId.Values); + private object GetState() => new RunningWorkflowsSnapshot(_lookupByInstanceId.Values.ToList()); private void RegisterInternal(RegisterRunningWorkflowRequest request) { - var entry = new WorkflowInstanceEntry(request.DefinitionId, request.Version, request.InstanceId, request.CorrelationId); + var entry = new RunningWorkflowInstanceEntry(request.DefinitionId, request.Version, request.InstanceId, request.CorrelationId); _lookupByInstanceId[request.InstanceId] = entry; if (!string.IsNullOrEmpty(request.CorrelationId)) @@ -96,6 +102,4 @@ public class RunningWorkflowsGrain : RunningWorkflowsGrainBase _lookupByInstanceId.Remove(request.InstanceId); } -} - -internal record WorkflowInstanceEntry(string DefinitionId, int Version, string InstanceId, string? CorrelationId); \ No newline at end of file +} \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor/Grains/WorkflowGrain.cs b/src/modules/Elsa.ProtoActor/Grains/WorkflowInstance.cs similarity index 97% rename from src/modules/Elsa.ProtoActor/Grains/WorkflowGrain.cs rename to src/modules/Elsa.ProtoActor/Grains/WorkflowInstance.cs index ba6dc4c8f..e32c2e17d 100644 --- a/src/modules/Elsa.ProtoActor/Grains/WorkflowGrain.cs +++ b/src/modules/Elsa.ProtoActor/Grains/WorkflowInstance.cs @@ -1,7 +1,8 @@ using Elsa.Common.Models; +using Elsa.Extensions; using Elsa.ProtoActor.Extensions; using Elsa.ProtoActor.Mappers; -using Elsa.ProtoActor.Protos; +using Elsa.ProtoActor.ProtoBuf; using Elsa.Workflows.Core.Contracts; using Elsa.Workflows.Core.State; using Elsa.Workflows.Management.Contracts; @@ -11,14 +12,14 @@ using Proto.Cluster; using Proto.Persistence; using Exception = System.Exception; using WorkflowStatus = Elsa.Workflows.Core.WorkflowStatus; -using ProtoBookmark = Elsa.ProtoActor.Protos.Bookmark; +using ProtoBookmark = Elsa.ProtoActor.ProtoBuf.Bookmark; namespace Elsa.ProtoActor.Grains; /// /// Executes a workflow. /// -internal class WorkflowGrain : WorkflowGrainBase +internal class WorkflowInstance : WorkflowInstanceBase { private const int MaxSnapshotsToKeep = 5; private readonly IWorkflowDefinitionService _workflowDefinitionService; @@ -38,7 +39,7 @@ internal class WorkflowGrain : WorkflowGrainBase private WorkflowState _workflowState = default!; /// - public WorkflowGrain( + public WorkflowInstance( IWorkflowDefinitionService workflowDefinitionService, IWorkflowHostFactory workflowHostFactory, IWorkflowStateSerializer workflowStateSerializer, @@ -140,7 +141,7 @@ internal class WorkflowGrain : WorkflowGrainBase var startWorkflowOptions = new StartWorkflowHostOptions(instanceId, correlationId, input, request.TriggerActivityId); await _workflowHost.StartWorkflowAsync(startWorkflowOptions, cancellationToken); var workflowState = _workflowHost.WorkflowState; - var result = workflowState.Status == WorkflowStatus.Finished ? Protos.RunWorkflowResult.Finished : Protos.RunWorkflowResult.Suspended; + var result = workflowState.Status == WorkflowStatus.Finished ? ProtoBuf.RunWorkflowResult.Finished : ProtoBuf.RunWorkflowResult.Suspended; _workflowState = workflowState; @@ -261,7 +262,7 @@ internal class WorkflowGrain : WorkflowGrainBase await _persistence.PersistRollingSnapshotAsync(GetState(), MaxSnapshotsToKeep); } - private object GetState() => new WorkflowSnapshot(_definitionId, _instanceId, _version, _workflowState, _input); + private object GetState() => new WorkflowSnapshot(_definitionId, _instanceId, _version, _workflowState, _input?.ToDictionary(x => x.Key, x => x.Value)); private async Task CreateWorkflowHostAsync(string definitionId, VersionOptions versionOptions, CancellationToken cancellationToken) { diff --git a/src/modules/Elsa.ProtoActor/Handlers/StopRunningWorkflows.cs b/src/modules/Elsa.ProtoActor/Handlers/StopRunningWorkflows.cs index 3e9a8472e..91b6f128a 100644 --- a/src/modules/Elsa.ProtoActor/Handlers/StopRunningWorkflows.cs +++ b/src/modules/Elsa.ProtoActor/Handlers/StopRunningWorkflows.cs @@ -1,6 +1,6 @@ using Elsa.Extensions; using Elsa.Mediator.Contracts; -using Elsa.ProtoActor.Protos; +using Elsa.ProtoActor.ProtoBuf; using Elsa.Workflows.Management.Notifications; using JetBrains.Annotations; using Proto.Cluster; diff --git a/src/modules/Elsa.ProtoActor/Handlers/UpdateRunningWorkflows.cs b/src/modules/Elsa.ProtoActor/Handlers/UpdateRunningWorkflows.cs index eb61a4011..015896fe8 100644 --- a/src/modules/Elsa.ProtoActor/Handlers/UpdateRunningWorkflows.cs +++ b/src/modules/Elsa.ProtoActor/Handlers/UpdateRunningWorkflows.cs @@ -2,7 +2,7 @@ using Elsa.Extensions; using Elsa.Mediator.Contracts; using Elsa.ProtoActor.Extensions; using Elsa.ProtoActor.Grains; -using Elsa.ProtoActor.Protos; +using Elsa.ProtoActor.ProtoBuf; using Elsa.Workflows.Core.Notifications; using JetBrains.Annotations; using Proto.Cluster; @@ -11,7 +11,7 @@ using WorkflowStatus = Elsa.Workflows.Core.WorkflowStatus; namespace Elsa.ProtoActor.Handlers; /// -/// Updates the with running workflow instances. +/// Updates the with running workflow instances. /// [PublicAPI] internal class UpdateRunningWorkflows : INotificationHandler diff --git a/src/modules/Elsa.ProtoActor/Mappers/BookmarkMapper.cs b/src/modules/Elsa.ProtoActor/Mappers/BookmarkMapper.cs index cf2de23c3..a5b918c5b 100644 --- a/src/modules/Elsa.ProtoActor/Mappers/BookmarkMapper.cs +++ b/src/modules/Elsa.ProtoActor/Mappers/BookmarkMapper.cs @@ -1,7 +1,7 @@ using Elsa.ProtoActor.Extensions; using Elsa.Workflows.Core.Contracts; using Elsa.Workflows.Core.Models; -using ProtoBookmark = Elsa.ProtoActor.Protos.Bookmark; +using ProtoBookmark = Elsa.ProtoActor.ProtoBuf.Bookmark; namespace Elsa.ProtoActor.Mappers; diff --git a/src/modules/Elsa.ProtoActor/Mappers/ExceptionMapper.cs b/src/modules/Elsa.ProtoActor/Mappers/ExceptionMapper.cs index d8c6a4786..68d888ba7 100644 --- a/src/modules/Elsa.ProtoActor/Mappers/ExceptionMapper.cs +++ b/src/modules/Elsa.ProtoActor/Mappers/ExceptionMapper.cs @@ -1,5 +1,5 @@ using Elsa.Workflows.Core.State; -using ProtoException = Elsa.ProtoActor.Protos.ExceptionState; +using ProtoException = Elsa.ProtoActor.ProtoBuf.ExceptionState; namespace Elsa.ProtoActor.Mappers; diff --git a/src/modules/Elsa.ProtoActor/Mappers/WorkflowExecutionResultMapper.cs b/src/modules/Elsa.ProtoActor/Mappers/WorkflowExecutionResultMapper.cs index ea4f9f98b..f00a87fdf 100644 --- a/src/modules/Elsa.ProtoActor/Mappers/WorkflowExecutionResultMapper.cs +++ b/src/modules/Elsa.ProtoActor/Mappers/WorkflowExecutionResultMapper.cs @@ -1,6 +1,6 @@ using Elsa.ProtoActor.Extensions; using Elsa.Workflows.Runtime.Contracts; -using ProtoWorkflowExecutionResponse = Elsa.ProtoActor.Protos.WorkflowExecutionResponse; +using ProtoWorkflowExecutionResponse = Elsa.ProtoActor.ProtoBuf.WorkflowExecutionResponse; namespace Elsa.ProtoActor.Mappers; diff --git a/src/modules/Elsa.ProtoActor/Mappers/WorkflowFaultStateMapper.cs b/src/modules/Elsa.ProtoActor/Mappers/WorkflowFaultStateMapper.cs index 8fafbc819..a65b3b027 100644 --- a/src/modules/Elsa.ProtoActor/Mappers/WorkflowFaultStateMapper.cs +++ b/src/modules/Elsa.ProtoActor/Mappers/WorkflowFaultStateMapper.cs @@ -1,5 +1,5 @@ using Elsa.Workflows.Core.State; -using ProtoWorkflowFault = Elsa.ProtoActor.Protos.WorkflowFault; +using ProtoWorkflowFault = Elsa.ProtoActor.ProtoBuf.WorkflowFault; namespace Elsa.ProtoActor.Mappers; diff --git a/src/modules/Elsa.ProtoActor/Mappers/WorkflowStatusMapper.cs b/src/modules/Elsa.ProtoActor/Mappers/WorkflowStatusMapper.cs index b6073fe79..80b599aff 100644 --- a/src/modules/Elsa.ProtoActor/Mappers/WorkflowStatusMapper.cs +++ b/src/modules/Elsa.ProtoActor/Mappers/WorkflowStatusMapper.cs @@ -1,5 +1,5 @@ using Elsa.Workflows.Core; -using ProtoWorkflowStatus = Elsa.ProtoActor.Protos.WorkflowStatus; +using ProtoWorkflowStatus = Elsa.ProtoActor.ProtoBuf.WorkflowStatus; namespace Elsa.ProtoActor.Mappers; diff --git a/src/modules/Elsa.ProtoActor/Mappers/WorkflowSubStatusMapper.cs b/src/modules/Elsa.ProtoActor/Mappers/WorkflowSubStatusMapper.cs index aa996f33d..8ebdc92ff 100644 --- a/src/modules/Elsa.ProtoActor/Mappers/WorkflowSubStatusMapper.cs +++ b/src/modules/Elsa.ProtoActor/Mappers/WorkflowSubStatusMapper.cs @@ -1,5 +1,5 @@ using Elsa.Workflows.Core; -using ProtoWorkflowSubStatus = Elsa.ProtoActor.Protos.WorkflowSubStatus; +using ProtoWorkflowSubStatus = Elsa.ProtoActor.ProtoBuf.WorkflowSubStatus; namespace Elsa.ProtoActor.Mappers; diff --git a/src/modules/Elsa.ProtoActor/Models/RunningWorkflowInstanceEntry.cs b/src/modules/Elsa.ProtoActor/Models/RunningWorkflowInstanceEntry.cs new file mode 100644 index 000000000..d0b0d93fa --- /dev/null +++ b/src/modules/Elsa.ProtoActor/Models/RunningWorkflowInstanceEntry.cs @@ -0,0 +1,10 @@ +namespace Elsa.ProtoActor.Models; + +/// +/// A snapshot of information about a running workflow instance. +/// +/// The workflow definition id. +/// The workflow definition version. +/// The workflow instance ID. +/// The workflow instance correlation ID. +public record RunningWorkflowInstanceEntry(string DefinitionId, int Version, string InstanceId, string? CorrelationId); \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor/Proto/RunningWorkflows.Messages.proto b/src/modules/Elsa.ProtoActor/Proto/RunningWorkflows.Messages.proto new file mode 100644 index 000000000..974657bb2 --- /dev/null +++ b/src/modules/Elsa.ProtoActor/Proto/RunningWorkflows.Messages.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; +option csharp_namespace = "Elsa.ProtoActor.ProtoBuf"; +package Elsa.ProtoActor.ProtoBuf; + +import "google/protobuf/empty.proto"; +import "Shared.proto"; + +message RegisterRunningWorkflowRequest { + string DefinitionId = 1; + int32 Version = 2; + string InstanceId = 3; + optional string CorrelationId = 6; +} + +message UnregisterRunningWorkflowRequest { + string InstanceId = 1; +} + +message CountRunningWorkflowsRequest { + string DefinitionId = 1; + int32 Version = 2; + optional string CorrelationId = 3; +} + +message CountRunningWorkflowsResponse { + optional int32 Count = 1; +} \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor/Proto/RunningWorkflows.proto b/src/modules/Elsa.ProtoActor/Proto/RunningWorkflows.proto new file mode 100644 index 000000000..22bba7b54 --- /dev/null +++ b/src/modules/Elsa.ProtoActor/Proto/RunningWorkflows.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; +option csharp_namespace = "Elsa.ProtoActor.ProtoBuf"; +package Elsa.ProtoActor.ProtoBuf; + +import "google/protobuf/empty.proto"; +import "Shared.proto"; +import "RunningWorkflows.Messages.proto"; + +service RunningWorkflows { + rpc Register(RegisterRunningWorkflowRequest) returns (google.protobuf.Empty); + rpc Unregister(UnregisterRunningWorkflowRequest) returns (google.protobuf.Empty); + rpc Count (CountRunningWorkflowsRequest) returns (CountRunningWorkflowsResponse); +} \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor/Proto/Shared.proto b/src/modules/Elsa.ProtoActor/Proto/Shared.proto new file mode 100644 index 000000000..de2453b4b --- /dev/null +++ b/src/modules/Elsa.ProtoActor/Proto/Shared.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; +option csharp_namespace = "Elsa.ProtoActor.ProtoBuf"; +package Elsa.ProtoActor.ProtoBuf; + +import "google/protobuf/empty.proto"; +import "google/protobuf/wrappers.proto"; + +// Shared. +message Json { + string text = 1; +} + +message Input { + map Data = 1; +} \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor/Protos/Messages.proto b/src/modules/Elsa.ProtoActor/Proto/WorkflowInstance.Messages.proto similarity index 76% rename from src/modules/Elsa.ProtoActor/Protos/Messages.proto rename to src/modules/Elsa.ProtoActor/Proto/WorkflowInstance.Messages.proto index 11d7f673f..213719c06 100644 --- a/src/modules/Elsa.ProtoActor/Protos/Messages.proto +++ b/src/modules/Elsa.ProtoActor/Proto/WorkflowInstance.Messages.proto @@ -1,19 +1,11 @@ syntax = "proto3"; +option csharp_namespace = "Elsa.ProtoActor.ProtoBuf"; +package Elsa.ProtoActor.ProtoBuf; + import "google/protobuf/empty.proto"; import "google/protobuf/wrappers.proto"; -package Elsa.ProtoActor.Protos; -option csharp_namespace = "Elsa.ProtoActor.Protos"; +import "Shared.proto"; -// Shared. -message Json { - string text = 1; -} - -message Input { - map Data = 1; -} - -// WorkflowGrain. message CanStartWorkflowResponse { bool CanStart = 1; } @@ -102,26 +94,4 @@ message Bookmark { optional bool AutoBurn = 8; optional string CallbackMethodName = 9; string CreatedAt = 10; // ISO 8601 -} - -// RunningWorkflowsGrain. -message RegisterRunningWorkflowRequest { - string DefinitionId = 1; - int32 Version = 2; - string InstanceId = 3; - optional string CorrelationId = 6; -} - -message UnregisterRunningWorkflowRequest { - string InstanceId = 1; -} - -message CountRunningWorkflowsRequest { - string DefinitionId = 1; - int32 Version = 2; - optional string CorrelationId = 3; -} - -message CountRunningWorkflowsResponse { - optional int32 Count = 1; } \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor/Protos/Grains.proto b/src/modules/Elsa.ProtoActor/Proto/WorkflowInstance.proto similarity index 55% rename from src/modules/Elsa.ProtoActor/Protos/Grains.proto rename to src/modules/Elsa.ProtoActor/Proto/WorkflowInstance.proto index f38d4a901..1e5b533ac 100644 --- a/src/modules/Elsa.ProtoActor/Protos/Grains.proto +++ b/src/modules/Elsa.ProtoActor/Proto/WorkflowInstance.proto @@ -1,21 +1,17 @@ syntax = "proto3"; - -option csharp_namespace = "Elsa.ProtoActor.Protos"; +option csharp_namespace = "Elsa.ProtoActor.ProtoBuf"; +package Elsa.ProtoActor.ProtoBuf; import "google/protobuf/empty.proto"; -import "Messages.proto"; +import "google/protobuf/wrappers.proto"; +import "Shared.proto"; +import "WorkflowInstance.Messages.proto"; -service WorkflowGrain { +service WorkflowInstance { rpc CanStart (StartWorkflowRequest) returns (CanStartWorkflowResponse); rpc Start (StartWorkflowRequest) returns (WorkflowExecutionResponse); rpc Stop (Empty) returns (Empty); rpc Resume (ResumeWorkflowRequest) returns (WorkflowExecutionResponse); rpc ExportState(ExportWorkflowStateRequest) returns (ExportWorkflowStateResponse); rpc ImportState(ImportWorkflowStateRequest) returns (ImportWorkflowStateResponse); -} - -service RunningWorkflowsGrain { - rpc Register(RegisterRunningWorkflowRequest) returns (google.protobuf.Empty); - rpc Unregister(UnregisterRunningWorkflowRequest) returns (google.protobuf.Empty); - rpc Count (CountRunningWorkflowsRequest) returns (CountRunningWorkflowsResponse); } \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor/Services/ProtoActorWorkflowRuntime.cs b/src/modules/Elsa.ProtoActor/Services/ProtoActorWorkflowRuntime.cs index 399e87cb3..c7f750a1d 100644 --- a/src/modules/Elsa.ProtoActor/Services/ProtoActorWorkflowRuntime.cs +++ b/src/modules/Elsa.ProtoActor/Services/ProtoActorWorkflowRuntime.cs @@ -2,7 +2,7 @@ using Elsa.Common.Models; using Elsa.Extensions; using Elsa.ProtoActor.Extensions; using Elsa.ProtoActor.Mappers; -using Elsa.ProtoActor.Protos; +using Elsa.ProtoActor.ProtoBuf; using Elsa.Workflows.Core.Contracts; using Elsa.Workflows.Core.State; using Elsa.Workflows.Management.Contracts; @@ -11,12 +11,12 @@ using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; using Proto.Cluster; using Bookmark = Elsa.Workflows.Core.Models.Bookmark; -using ProtoWorkflowStatus = Elsa.ProtoActor.Protos.WorkflowStatus; -using ProtoWorkflowSubStatus = Elsa.ProtoActor.Protos.WorkflowSubStatus; -using ProtoWorkflowFault = Elsa.ProtoActor.Protos.WorkflowFault; -using ProtoException = Elsa.ProtoActor.Protos.ExceptionState; -using ProtoWorkflowExecutionResponse = Elsa.ProtoActor.Protos.WorkflowExecutionResponse; -using ProtoBookmark = Elsa.ProtoActor.Protos.Bookmark; +using ProtoWorkflowStatus = Elsa.ProtoActor.ProtoBuf.WorkflowStatus; +using ProtoWorkflowSubStatus = Elsa.ProtoActor.ProtoBuf.WorkflowSubStatus; +using ProtoWorkflowFault = Elsa.ProtoActor.ProtoBuf.WorkflowFault; +using ProtoException = Elsa.ProtoActor.ProtoBuf.ExceptionState; +using ProtoWorkflowExecutionResponse = Elsa.ProtoActor.ProtoBuf.WorkflowExecutionResponse; +using ProtoBookmark = Elsa.ProtoActor.ProtoBuf.Bookmark; namespace Elsa.ProtoActor.Services; diff --git a/src/modules/Elsa.ProtoActor/Snapshots.cs b/src/modules/Elsa.ProtoActor/Snapshots.cs index 5acafc12e..b6c52265f 100644 --- a/src/modules/Elsa.ProtoActor/Snapshots.cs +++ b/src/modules/Elsa.ProtoActor/Snapshots.cs @@ -1,8 +1,8 @@ -using Elsa.ProtoActor.Grains; +using Elsa.ProtoActor.Models; using Elsa.Workflows.Core.State; namespace Elsa.ProtoActor; -internal record WorkflowSnapshot(string DefinitionId, string InstanceId, int Version, WorkflowState WorkflowState, IDictionary? Input); +internal record WorkflowSnapshot(string DefinitionId, string InstanceId, int Version, WorkflowState WorkflowState, Dictionary? Input); -internal record WorkflowRegistrySnapshot(ICollection Entries); \ No newline at end of file +internal record RunningWorkflowsSnapshot(List Entries); \ No newline at end of file diff --git a/src/samples/aspnet/Elsa.Samples.AspNet.ProtoActorRuntime.AzureContainerApps/Program.cs b/src/samples/aspnet/Elsa.Samples.AspNet.ProtoActorRuntime.AzureContainerApps/Program.cs index d1ca285a9..9a85fe692 100644 --- a/src/samples/aspnet/Elsa.Samples.AspNet.ProtoActorRuntime.AzureContainerApps/Program.cs +++ b/src/samples/aspnet/Elsa.Samples.AspNet.ProtoActorRuntime.AzureContainerApps/Program.cs @@ -3,7 +3,7 @@ using Elsa.EntityFrameworkCore.Modules.Labels; using Elsa.EntityFrameworkCore.Modules.Management; using Elsa.EntityFrameworkCore.Modules.Runtime; using Elsa.Extensions; -using Elsa.ProtoActor.Protos; +using Elsa.ProtoActor.ProtoBuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Data.Sqlite; using Proto.Cluster.AzureContainerApps; @@ -69,7 +69,7 @@ services protoActor.RemoteConfig = _ => GrpcNetRemoteConfig .BindTo(advertisedHost) .WithProtoMessages(EmptyReflection.Descriptor) - .WithProtoMessages(MessagesReflection.Descriptor) + .WithProtoMessages(SharedReflection.Descriptor) .WithLogLevelForDeserializationErrors(LogLevel.Critical) .WithRemoteDiagnostics(true); // required by proto.actor dashboard