diff --git a/Elsa.sln b/Elsa.sln index d95f59352..0b9d5e277 100644 --- a/Elsa.sln +++ b/Elsa.sln @@ -122,6 +122,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Jobs", "src\modules\El EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Common", "src\modules\Elsa.Common\Elsa.Common.csproj", "{D229105F-6879-4452-9189-75DE060C0F4C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.ProtoActor.Kubernetes", "src\modules\Elsa.ProtoActor.Kubernetes\Elsa.ProtoActor.Kubernetes.csproj", "{26087ED2-9249-4FF3-8869-C11C405E441A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.ProtoActor.Common", "src\modules\Elsa.ProtoActor.Common\Elsa.ProtoActor.Common.csproj", "{F599E891-598E-402F-A9B9-95D0B1C661F6}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.Console3", "src\samples\console\Elsa.Samples.Console3\Elsa.Samples.Console3.csproj", "{517B703A-7653-4036-AAB5-7B4293D39D0F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "worker", "worker", "{389D40B8-005F-46A1-9493-1FE6065F04FD}" @@ -330,14 +334,6 @@ Global {D229105F-6879-4452-9189-75DE060C0F4C}.Debug|Any CPU.Build.0 = Debug|Any CPU {D229105F-6879-4452-9189-75DE060C0F4C}.Release|Any CPU.ActiveCfg = Release|Any CPU {D229105F-6879-4452-9189-75DE060C0F4C}.Release|Any CPU.Build.0 = Release|Any CPU - {517B703A-7653-4036-AAB5-7B4293D39D0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {517B703A-7653-4036-AAB5-7B4293D39D0F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {517B703A-7653-4036-AAB5-7B4293D39D0F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {517B703A-7653-4036-AAB5-7B4293D39D0F}.Release|Any CPU.Build.0 = Release|Any CPU - {197223FB-2472-442C-BD10-2E1F931285BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {197223FB-2472-442C-BD10-2E1F931285BC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {197223FB-2472-442C-BD10-2E1F931285BC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {197223FB-2472-442C-BD10-2E1F931285BC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {155227F0-A33B-40AA-A4B4-06F813EB921B} = {61017E64-6D00-49CB-9E81-5002DC8F7D5F} @@ -396,7 +392,5 @@ Global {CF1938A0-BD10-4AA1-9ABC-6D02303A9D53} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} {D229105F-6879-4452-9189-75DE060C0F4C} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79} {517B703A-7653-4036-AAB5-7B4293D39D0F} = {873BFC3E-63C2-4495-A503-5EC05DCD84E4} - {389D40B8-005F-46A1-9493-1FE6065F04FD} = {155227F0-A33B-40AA-A4B4-06F813EB921B} - {197223FB-2472-442C-BD10-2E1F931285BC} = {389D40B8-005F-46A1-9493-1FE6065F04FD} EndGlobalSection EndGlobal diff --git a/src/modules/Elsa.ProtoActor.Common/DependencyInjectionExtensions.cs b/src/modules/Elsa.ProtoActor.Common/DependencyInjectionExtensions.cs new file mode 100644 index 000000000..7b9a1f62f --- /dev/null +++ b/src/modules/Elsa.ProtoActor.Common/DependencyInjectionExtensions.cs @@ -0,0 +1,26 @@ +using Elsa.ProtoActor.Common.Options; +using Proto; + +namespace Elsa.ProtoActor.Common; + +public static class DependencyInjectionExtensions +{ + public static ActorSystemConfig WithDeveloperLogging(this ActorSystemConfig actorSystemConfig, Action? developerLoggingOption = null) + { + var options = new DeveloperLoggingOptions(); + developerLoggingOption?.Invoke(options); + + return actorSystemConfig.WithDeveloperSupervisionLogging(true) + .WithDeveloperReceiveLogging(options.ReceiveLoggingTimeSpan) + .WithDeadLetterThrottleCount(options.DeadLetterThrottleCount) + .WithDeadLetterThrottleInterval(options.DeadLetterThrottleInterval) + .WithDeadLetterRequestLogging(true); + } + + public static ActorSystemConfig ConfigureActorSystemConfig(this ActorSystemConfig systemConfig, + Action callback) + { + callback(systemConfig); + return systemConfig; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor.Common/Elsa.ProtoActor.Common.csproj b/src/modules/Elsa.ProtoActor.Common/Elsa.ProtoActor.Common.csproj new file mode 100644 index 000000000..ee031a3a1 --- /dev/null +++ b/src/modules/Elsa.ProtoActor.Common/Elsa.ProtoActor.Common.csproj @@ -0,0 +1,18 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + + diff --git a/src/modules/Elsa.ProtoActor.Common/Options/ClusterConfigurationSettings.cs b/src/modules/Elsa.ProtoActor.Common/Options/ClusterConfigurationSettings.cs new file mode 100644 index 000000000..436be782f --- /dev/null +++ b/src/modules/Elsa.ProtoActor.Common/Options/ClusterConfigurationSettings.cs @@ -0,0 +1,9 @@ +namespace Elsa.ProtoActor.Common.Options; + +public class ClusterConfigurationSettings +{ + public TimeSpan HeartBeatExpiration { get; set; } = TimeSpan.FromDays(1); + public TimeSpan ActorRequestTimeout { get; set; } = TimeSpan.FromHours(1); + public TimeSpan ActorActivationTimeout { get; set; } = TimeSpan.FromHours(1); + public TimeSpan ActorSpawnTimeout { get; set; } = TimeSpan.FromHours(1); +} \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor.Common/Options/DeveloperLoggingOptions.cs b/src/modules/Elsa.ProtoActor.Common/Options/DeveloperLoggingOptions.cs new file mode 100644 index 000000000..608184f51 --- /dev/null +++ b/src/modules/Elsa.ProtoActor.Common/Options/DeveloperLoggingOptions.cs @@ -0,0 +1,8 @@ +namespace Elsa.ProtoActor.Common.Options; + +public class DeveloperLoggingOptions +{ + public TimeSpan ReceiveLoggingTimeSpan { get; set; } = TimeSpan.FromHours(1); + public int DeadLetterThrottleCount { get; set; } = 3; + public TimeSpan DeadLetterThrottleInterval { get; set; } = TimeSpan.FromSeconds(10000); +} \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor.Common/Options/ProviderOptions.cs b/src/modules/Elsa.ProtoActor.Common/Options/ProviderOptions.cs new file mode 100644 index 000000000..857c4efdb --- /dev/null +++ b/src/modules/Elsa.ProtoActor.Common/Options/ProviderOptions.cs @@ -0,0 +1,10 @@ +namespace Elsa.ProtoActor.Common.Options; + +public class ProviderOptions +{ + public string Name { get; set; } = "elsa-cluster"; + + public bool WithDeveloperLogging { get; set; } = true; + + public bool WithMetrics { get; set; } +} diff --git a/src/modules/Elsa.ProtoActor.Common/ProtoActorBuilder.cs b/src/modules/Elsa.ProtoActor.Common/ProtoActorBuilder.cs new file mode 100644 index 000000000..02a366db8 --- /dev/null +++ b/src/modules/Elsa.ProtoActor.Common/ProtoActorBuilder.cs @@ -0,0 +1,54 @@ +using Elsa.ProtoActor.Common.Options; +using Proto; +using Proto.Cluster; +using Proto.Cluster.Identity; +using Proto.Remote.GrpcNet; + +namespace Elsa.ProtoActor.Common; + +public class ProtoActorBuilder +{ + ProtoActorSystem protoActorSystem = new (); + public ProtoActorBuilder WithClusterProvider(IClusterProvider clusterProvider) + { + protoActorSystem.ClusterProvider = clusterProvider; + return this; + } + + public ProtoActorBuilder WithRemoteConfig(GrpcNetRemoteConfig remoteConfig) + { + protoActorSystem.RemoteConfig = remoteConfig; + return this; + } + + public ProtoActorSystem Build() => protoActorSystem; + + public ProtoActorBuilder WithOptions() + { + return this; + } + + public ProtoActorBuilder WithIdentity(IIdentityLookup identityLookup) + { + protoActorSystem.IdentityLookup = identityLookup; + return this; + } + + public ProtoActorBuilder WithClusterName(string name) + { + protoActorSystem.Name = name; + return this; + } + + public ProtoActorBuilder WithClusterConfiguration(ClusterConfigurationSettings settings) + { + protoActorSystem.ClusterConfigurationSettings = settings; + return this; + } + + public ProtoActorBuilder WithActorSystemConfig(ActorSystemConfig actorSystemConfig) + { + protoActorSystem.ActorSystemConfig = actorSystemConfig; + return this; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor.Common/ProtoActorSystem.cs b/src/modules/Elsa.ProtoActor.Common/ProtoActorSystem.cs new file mode 100644 index 000000000..981db6eaf --- /dev/null +++ b/src/modules/Elsa.ProtoActor.Common/ProtoActorSystem.cs @@ -0,0 +1,33 @@ +using Elsa.ProtoActor.Common.Options; +using Proto; +using Proto.Cluster; +using Proto.Cluster.Identity; +using Proto.Remote.GrpcNet; + +namespace Elsa.ProtoActor.Common; + +public class ProtoActorSystem +{ + public IClusterProvider ClusterProvider { get; set; } + public GrpcNetRemoteConfig RemoteConfig { get; set; } + public ActorSystemConfig ActorSystemConfig { get; set; } = ActorSystemConfig.Setup(); + public IIdentityLookup IdentityLookup { get; set; } + + public ClusterConfigurationSettings ClusterConfigurationSettings { get; set; } = new(); + + public string Name { get; set; } + + public ProtoActorSystem(IClusterProvider clusterProvider, GrpcNetRemoteConfig remoteConfig, ActorSystemConfig actorSystemConfig, IIdentityLookup identityLookup, string name, ClusterConfigurationSettings clusterConfigurationSettings) + { + ClusterProvider = clusterProvider; + RemoteConfig = remoteConfig; + ActorSystemConfig = actorSystemConfig; + IdentityLookup = identityLookup; + Name = name; + ClusterConfigurationSettings = clusterConfigurationSettings; + } + + public ProtoActorSystem() + { + } +} \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor.Kubernetes/DependencyInjectionExtensions.cs b/src/modules/Elsa.ProtoActor.Kubernetes/DependencyInjectionExtensions.cs new file mode 100644 index 000000000..c28ce9ad4 --- /dev/null +++ b/src/modules/Elsa.ProtoActor.Kubernetes/DependencyInjectionExtensions.cs @@ -0,0 +1,18 @@ +using System; +using Elsa.ProtoActor.Common; +using Elsa.ProtoActor.Configuration; + +namespace Elsa.ProtoActor.Kubernetes; + +public static class DependencyInjectionExtensions +{ + public static ProtoActorFeature WithKubernetesProvider(this ProtoActorFeature protoActorFeature, Action providerOptions) + { + var options = new KubernetesProviderOptions(); + providerOptions?.Invoke(options); + + protoActorFeature.ConfigureProtoActorBuilder(sp => + new ProtoActorBuilder().UseKubernetesProvider(options).Build()); + return protoActorFeature; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor.Kubernetes/Elsa.ProtoActor.Kubernetes.csproj b/src/modules/Elsa.ProtoActor.Kubernetes/Elsa.ProtoActor.Kubernetes.csproj new file mode 100644 index 000000000..7cfbbeaf6 --- /dev/null +++ b/src/modules/Elsa.ProtoActor.Kubernetes/Elsa.ProtoActor.Kubernetes.csproj @@ -0,0 +1,21 @@ + + + + net6.0 + enable + + + + + + + + + + + + + + + + diff --git a/src/modules/Elsa.ProtoActor.Kubernetes/KubernetesProviderOptions.cs b/src/modules/Elsa.ProtoActor.Kubernetes/KubernetesProviderOptions.cs new file mode 100644 index 000000000..97b47708f --- /dev/null +++ b/src/modules/Elsa.ProtoActor.Kubernetes/KubernetesProviderOptions.cs @@ -0,0 +1,12 @@ +using Elsa.ProtoActor.Common.Options; +using Proto.Cluster.Identity; +using Proto.Cluster.Partition; + +namespace Elsa.ProtoActor.Kubernetes; + +public class KubernetesProviderOptions : ProviderOptions +{ + public string HostAddress { get; set; } + + public IIdentityLookup IdentityLookup { get; set; } = new PartitionIdentityLookup(); +} \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor.Kubernetes/ProtoActorBuilderExtensions.cs b/src/modules/Elsa.ProtoActor.Kubernetes/ProtoActorBuilderExtensions.cs new file mode 100644 index 000000000..1eeb350b8 --- /dev/null +++ b/src/modules/Elsa.ProtoActor.Kubernetes/ProtoActorBuilderExtensions.cs @@ -0,0 +1,49 @@ +using System; +using Elsa.ProtoActor.Common; +using Microsoft.Extensions.Logging; +using Proto; +using Proto.Cluster; +using Proto.Cluster.Kubernetes; +using Proto.Cluster.Partition; +using Proto.Remote; +using Proto.Remote.GrpcNet; + +namespace Elsa.ProtoActor.Kubernetes; + +public static class ProtoActorBuilderExtensions +{ + public static ProtoActorBuilder UseKubernetesProvider(this ProtoActorBuilder builder, KubernetesProviderOptions options) + { + var (remoteConfig, clusterProvider) = ConfigureForKubernetes(options.HostAddress); + + var actorSystemConfig = ActorSystemConfig.Setup(); + if (options.WithDeveloperLogging) + { + actorSystemConfig.WithDeveloperLogging(); + } + + if (options.WithMetrics) + { + actorSystemConfig.WithMetrics(); + } + + builder.WithClusterProvider(clusterProvider) + .WithRemoteConfig(remoteConfig) + .WithClusterName(options.Name) + .WithIdentity(options.IdentityLookup) + .WithActorSystemConfig(actorSystemConfig); + return builder; + } + + private static (GrpcNetRemoteConfig, IClusterProvider) ConfigureForKubernetes(string host) + { + var clusterProvider = new KubernetesProvider(); + + var remoteConfig = GrpcNetRemoteConfig + .BindToAllInterfaces(advertisedHost: host) + .WithLogLevelForDeserializationErrors(LogLevel.Critical) + .WithRemoteDiagnostics(true); + + return (remoteConfig, clusterProvider); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor/Configuration/ProtoActorFeature.cs b/src/modules/Elsa.ProtoActor/Configuration/ProtoActorFeature.cs index 2e7d0635e..4a5b22346 100644 --- a/src/modules/Elsa.ProtoActor/Configuration/ProtoActorFeature.cs +++ b/src/modules/Elsa.ProtoActor/Configuration/ProtoActorFeature.cs @@ -2,17 +2,18 @@ using System; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; using Elsa.Features.Services; +using Elsa.ProtoActor.Common; +using Elsa.ProtoActor.Extensions; using Elsa.ProtoActor.Grains; using Elsa.ProtoActor.HostedServices; using Elsa.ProtoActor.Implementations; using Elsa.Runtime.Protos; using Elsa.Workflows.Runtime.Features; +using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Proto; using Proto.Cluster; -using Proto.Cluster.Partition; -using Proto.Cluster.Testing; using Proto.DependencyInjection; using Proto.Remote; using Proto.Remote.GrpcNet; @@ -29,23 +30,50 @@ public class ProtoActorFeature : FeatureBase public override void Configure() { // Configure runtime with ProtoActor workflow invoker. - Module.Configure().WorkflowInvokerFactory = sp => ActivatorUtilities.CreateInstance(sp); + Module.Configure().WorkflowInvokerFactory = + sp => ActivatorUtilities.CreateInstance(sp); } + public ProtoActorFeature ConfigureProtoActorBuilder(Func factory) + { + ProtoActorBuilderFactory = factory; + return this; + } + + //configure the default one + public Func ProtoActorBuilderFactory { get; set; } = + _ => new ProtoActorBuilder().UseLocalhostProvider("elsa-cluster", true) .Build(); + public override void Apply() { var services = Services; - var systemConfig = GetSystemConfig(); + services.AddSingleton(ProtoActorBuilderFactory); // Logging. Log.SetLoggerFactory(LoggerFactory.Create(l => l.AddConsole().SetMinimumLevel(LogLevel.Warning))); - // Actor System. services.AddSingleton(sp => { - var system = new ActorSystem(systemConfig).WithServiceProvider(sp); - var remoteConfig = GetRemoteConfig(); - var clusterConfig = GetClusterConfig(system, "my-cluster"); + var protoActorSystem = sp.GetService(); + + var system = new ActorSystem(protoActorSystem!.ActorSystemConfig).WithServiceProvider(sp); + + var remoteConfig = protoActorSystem.RemoteConfig + .WithProtoMessages(MessagesReflection.Descriptor) + .WithProtoMessages(EmptyReflection.Descriptor); + + var workflowDefinitionProps = system.DI().PropsFor(); + var workflowInstanceProps = system.DI().PropsFor(); + + var clusterConfig = + ClusterConfig + .Setup(protoActorSystem.Name, protoActorSystem.ClusterProvider, protoActorSystem.IdentityLookup) + .WithHeartbeatExpiration(protoActorSystem.ClusterConfigurationSettings.HeartBeatExpiration) + .WithActorRequestTimeout(protoActorSystem.ClusterConfigurationSettings.ActorRequestTimeout) + .WithActorActivationTimeout(protoActorSystem.ClusterConfigurationSettings.ActorActivationTimeout) + .WithActorSpawnTimeout(protoActorSystem.ClusterConfigurationSettings.ActorSpawnTimeout) + .WithClusterKind(WorkflowDefinitionGrainActor.Kind, workflowDefinitionProps) + .WithClusterKind(WorkflowInstanceGrainActor.Kind, workflowInstanceProps); system .WithRemote(remoteConfig) @@ -59,8 +87,10 @@ public class ProtoActorFeature : FeatureBase // Actors. services - .AddSingleton(sp => new WorkflowDefinitionGrainActor((context, _) => ActivatorUtilities.CreateInstance(sp, context))) - .AddSingleton(sp => new WorkflowInstanceGrainActor((context, _) => ActivatorUtilities.CreateInstance(sp, context))); + .AddSingleton(sp => new WorkflowDefinitionGrainActor((context, _) => + ActivatorUtilities.CreateInstance(sp, context))) + .AddSingleton(sp => new WorkflowInstanceGrainActor((context, _) => + ActivatorUtilities.CreateInstance(sp, context))); // Client factory. services.AddSingleton(); @@ -70,46 +100,4 @@ public class ProtoActorFeature : FeatureBase { Services.AddHostedService(); } - - private static ActorSystemConfig GetSystemConfig() => - ActorSystemConfig - .Setup() - .WithDeveloperSupervisionLogging(true) - .WithDeveloperReceiveLogging(TimeSpan.FromHours(1)) - .WithDeadLetterThrottleCount(3) - .WithDeadLetterThrottleInterval(TimeSpan.FromSeconds(10000)) - .WithDeveloperSupervisionLogging(true) - .WithDeadLetterRequestLogging(true); - - private static GrpcNetRemoteConfig GetRemoteConfig() => Proto.Remote.GrpcNet.GrpcNetRemoteConfig - .BindToLocalhost() - .WithProtoMessages(MessagesReflection.Descriptor); - - private static ClusterConfig GetClusterConfig(ActorSystem system, string clusterName) - { - //var clusterProvider = new ConsulProvider(new ConsulProviderConfig{}); - var clusterProvider = new TestProvider(new TestProviderOptions(), new InMemAgent()); - - var workflowDefinitionProps = system.DI().PropsFor(); - var workflowInstanceProps = system.DI().PropsFor(); - - var clusterConfig = - ClusterConfig - // .Setup("MyCluster", clusterProvider, new IdentityStorageLookup(GetIdentityLookup(clusterName))) - .Setup(clusterName, clusterProvider, new PartitionIdentityLookup()) - .WithHeartbeatExpiration(TimeSpan.FromDays(1)) - //.WithTimeout(TimeSpan.FromHours(1)) - .WithActorRequestTimeout(TimeSpan.FromHours(1)) - .WithActorActivationTimeout(TimeSpan.FromHours(1)) - .WithActorSpawnTimeout(TimeSpan.FromHours(1)) - .WithClusterKind(WorkflowDefinitionGrainActor.Kind, workflowDefinitionProps) - .WithClusterKind(WorkflowInstanceGrainActor.Kind, workflowInstanceProps) - ; - return clusterConfig; - } - - // private static IIdentityStorage GetIdentityLookup(string clusterName) => - // new RedisIdentityStorage(clusterName, ConnectionMultiplexer - // .Connect("localhost:6379" /* use proper config */) - // ); } \ No newline at end of file diff --git a/src/modules/Elsa.ProtoActor/Elsa.ProtoActor.csproj b/src/modules/Elsa.ProtoActor/Elsa.ProtoActor.csproj index d7785964f..0ed5fa944 100644 --- a/src/modules/Elsa.ProtoActor/Elsa.ProtoActor.csproj +++ b/src/modules/Elsa.ProtoActor/Elsa.ProtoActor.csproj @@ -27,6 +27,7 @@ + diff --git a/src/modules/Elsa.ProtoActor/Extensions/DependencyInjectionExtensions.cs b/src/modules/Elsa.ProtoActor/Extensions/DependencyInjectionExtensions.cs index dc3b9dc27..3ed53d81d 100644 --- a/src/modules/Elsa.ProtoActor/Extensions/DependencyInjectionExtensions.cs +++ b/src/modules/Elsa.ProtoActor/Extensions/DependencyInjectionExtensions.cs @@ -1,4 +1,6 @@ using System; +using Elsa.ProtoActor.Common; +using Elsa.ProtoActor.Common.Options; using Elsa.ProtoActor.Configuration; using Elsa.Workflows.Runtime.Features; @@ -11,4 +13,14 @@ public static class DependencyInjectionExtensions feature.Module.Configure(configure); return feature; } -} \ No newline at end of file + + public static ProtoActorFeature WithLocalhostProvider(this ProtoActorFeature protoActorFeature, Action? providerOptions = null) + { + var options = new ProviderOptions(); + providerOptions?.Invoke(options); + + protoActorFeature.ConfigureProtoActorBuilder(sp => + new ProtoActorBuilder().UseLocalhostProvider(options.Name, options.WithDeveloperLogging).Build()); + return protoActorFeature; + } +} diff --git a/src/modules/Elsa.ProtoActor/Extensions/ProtoActorBuilderExtensions.cs b/src/modules/Elsa.ProtoActor/Extensions/ProtoActorBuilderExtensions.cs new file mode 100644 index 000000000..f8e426958 --- /dev/null +++ b/src/modules/Elsa.ProtoActor/Extensions/ProtoActorBuilderExtensions.cs @@ -0,0 +1,23 @@ +using Elsa.ProtoActor.Common; +using Proto; +using Proto.Cluster.Partition; +using Proto.Cluster.Testing; +using Proto.Remote.GrpcNet; + +namespace Elsa.ProtoActor.Extensions; + +public static class ProtoActorBuilderExtensions +{ + public static ProtoActorBuilder UseLocalhostProvider(this ProtoActorBuilder builder, string clusterName, bool withDeveloperLogging) + { + var actorSystemConfig = ActorSystemConfig.Setup(); + + builder.WithClusterProvider(new TestProvider(new TestProviderOptions(), new InMemAgent())) + .WithRemoteConfig(GrpcNetRemoteConfig + .BindToLocalhost()) + .WithClusterName(clusterName) + .WithIdentity(new PartitionIdentityLookup()) + .WithActorSystemConfig(withDeveloperLogging ? actorSystemConfig.WithDeveloperLogging() : actorSystemConfig); + return builder; + } +} \ 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 664b9834c..5d9fa8b8a 100644 --- a/src/modules/Elsa.ProtoActor/Extensions/ProtoInputExtensions.cs +++ b/src/modules/Elsa.ProtoActor/Extensions/ProtoInputExtensions.cs @@ -16,7 +16,7 @@ public static class ProtoInputExtensions foreach (var (key, value) in input) { - data[key] = new Json + data[key] = new Runtime.Protos.Json { Text = JsonSerializer.Serialize(value) }; diff --git a/src/samples/aspnet/Elsa.Samples.Web2/Program.cs b/src/samples/aspnet/Elsa.Samples.Web2/Program.cs index 86d9b2c24..46dfb4e39 100644 --- a/src/samples/aspnet/Elsa.Samples.Web2/Program.cs +++ b/src/samples/aspnet/Elsa.Samples.Web2/Program.cs @@ -25,7 +25,7 @@ var services = builder.Services; services .AddElsa(elsa => elsa .UseWorkflows() - .UseRuntime(runtime => runtime.UseProtoActor()) + .UseRuntime(runtime => runtime.UseProtoActor(f=> f.WithLocalhostProvider(opt => opt.Name = "my-cluster"))) .UseManagement(management => management .AddActivity() .AddActivity()