Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand Remote and Cluster options #366

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/Akka.Cluster.Hosting.Tests/ClusterOptionsSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
using Akka.Cluster.SBR;
using Akka.Configuration;
using Akka.Hosting;
using Akka.Remote.Hosting;
using FluentAssertions;
using FluentAssertions.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -42,6 +44,8 @@ public void EmptyClusterOptionsTest()
settings.LogInfo.Should().BeTrue();
settings.LogInfoVerbose.Should().BeFalse();
settings.DowningProviderType.Should().Be(typeof(SplitBrainResolverProvider));
settings.HeartbeatInterval.Should().Be(1.Seconds());
settings.HeartbeatExpectedResponseAfter.Should().Be(1.Seconds());
}

[Fact(DisplayName = "ClusterOptions should generate proper HOCON values")]
Expand All @@ -64,6 +68,16 @@ public void ClusterOptionsTest()
SplitBrainResolver = new KeepMajorityOption
{
Role = "back-end"
},
FailureDetector = new PhiAccrualFailureDetectorOptions
{
HeartbeatInterval = 1.1.Seconds(),
AcceptableHeartbeatPause = 1.1.Seconds(),
Threshold = 1.1,
MaxSampleSize = 1,
MinStandardDeviation = 1.1.Seconds(),
UnreachableNodesReaperInterval = 1.1.Seconds(),
ExpectedResponseAfter = 1.1.Seconds()
}
});

Expand All @@ -86,6 +100,15 @@ public void ClusterOptionsTest()
var sbrConfig = builder.Configuration.Value.GetConfig("akka.cluster.split-brain-resolver");
sbrConfig.GetString("active-strategy").Should().Be(SplitBrainResolverSettings.KeepMajorityName);
sbrConfig.GetString($"{SplitBrainResolverSettings.KeepMajorityName}.role").Should().Be("back-end");

var detectorConfig = builder.Configuration.Value.GetConfig("akka.cluster.failure-detector");
detectorConfig.GetTimeSpan("heartbeat-interval").Should().Be(1.1.Seconds());
detectorConfig.GetTimeSpan("acceptable-heartbeat-pause").Should().Be(1.1.Seconds());
detectorConfig.GetDouble("threshold").Should().Be(1.1);
detectorConfig.GetInt("max-sample-size").Should().Be(1);
detectorConfig.GetTimeSpan("min-std-deviation").Should().Be(1.1.Seconds());
detectorConfig.GetTimeSpan("unreachable-nodes-reaper-interval").Should().Be(1.1.Seconds());
detectorConfig.GetTimeSpan("expected-response-after").Should().Be(1.1.Seconds());
}

[Fact(DisplayName = "ClusterOptions should be bindable using Microsoft.Extensions.Configuration")]
Expand Down
71 changes: 45 additions & 26 deletions src/Akka.Cluster.Hosting/AkkaClusterHostingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
using Akka.Hosting;
using Akka.Hosting.Coordination;
using Akka.Persistence.Hosting;
using Akka.Remote;
using Akka.Remote.Hosting;
using Akka.Util;

#nullable enable
Expand Down Expand Up @@ -114,6 +116,13 @@ public sealed class ClusterOptions
/// uses the keep majority resolving strategy.
/// </summary>
public SplitBrainResolverOption? SplitBrainResolver { get; set; }

/// <summary>
/// <para>
/// Settings for the failure detector used by the cluster subsystem to detect unreachable members.
/// </para>
/// </summary>
public PhiAccrualFailureDetectorOptions? FailureDetector { get; set; }
}

public sealed class ClusterSingletonOptions
Expand Down Expand Up @@ -299,39 +308,39 @@ internal void Apply(AkkaConfigurationBuilder builder)

var sb = new StringBuilder();

if (Role is { })
if (Role is not null)
sb.AppendLine($"role = {Role.ToHocon()}");

if(RememberEntities is { })
if(RememberEntities is not null)
sb.AppendLine($"remember-entities = {RememberEntities.ToHocon()}");

if(RememberEntitiesStore is { })
if(RememberEntitiesStore is not null)
sb.AppendLine($"remember-entities-store = {RememberEntitiesStore.ToString().ToLowerInvariant().ToHocon()}");

var journalId = JournalOptions?.PluginId ?? JournalPluginId ?? null;
if (journalId is { })
if (journalId is not null)
sb.AppendLine($"journal-plugin-id = {journalId.ToHocon()}");

var snapshotId = SnapshotOptions?.PluginId ?? SnapshotPluginId ?? null;
if (snapshotId is { })
if (snapshotId is not null)
sb.AppendLine($"snapshot-plugin-id = {snapshotId.ToHocon()}");

if (StateStoreMode is { })
if (StateStoreMode is not null)
sb.AppendLine($"state-store-mode = {StateStoreMode.ToString().ToLowerInvariant().ToHocon()}");

if (LeaseImplementation is { })
if (LeaseImplementation is not null)
sb.AppendLine($"use-lease = {LeaseImplementation.ConfigPath}");

if (LeaseRetryInterval is { })
if (LeaseRetryInterval is not null)
sb.AppendLine($"lease-retry-interval = {LeaseRetryInterval.ToHocon()}");

if (FailOnInvalidEntityStateTransition is { })
if (FailOnInvalidEntityStateTransition is not null)
sb.AppendLine(
$"fail-on-invalid-entity-state-transition = {FailOnInvalidEntityStateTransition.ToHocon()}");

if(ShouldPassivateIdleEntities is false)
sb.AppendLine("passivate-idle-entity-after = off");
else if(PassivateIdleEntityAfter is { })
else if(PassivateIdleEntityAfter is not null)
sb.AppendLine($"passivate-idle-entity-after = {PassivateIdleEntityAfter.ToHocon()}");

if (sb.Length > 0)
Expand All @@ -353,9 +362,9 @@ internal void Apply(AkkaConfigurationBuilder builder)
base.Apply(builder, "akka.cluster.sharding");

var sb = new StringBuilder();
if (MajorityMinimumCapacity is { })
if (MajorityMinimumCapacity is not null)
sb.AppendLine($"majority-min-cap = {MajorityMinimumCapacity}");
if (MaxDeltaElements is { })
if (MaxDeltaElements is not null)
sb.AppendLine($"max-delta-elements = {MaxDeltaElements}");

if(sb.Length == 0)
Expand Down Expand Up @@ -407,28 +416,28 @@ internal virtual void Apply(AkkaConfigurationBuilder builder, string prefix = "a
{
var sb = new StringBuilder();

if (Name is { })
if (Name is not null)
sb.AppendLine($"name = {Name.ToHocon()}");
if (Role is { })
if (Role is not null)
sb.AppendLine($"role = {Role.ToHocon()}");
if (RecreateOnFailure is { })
if (RecreateOnFailure is not null)
sb.AppendLine($"recreate-on-failure = {RecreateOnFailure.ToHocon()}");
if (PreferOldest is { })
if (PreferOldest is not null)
sb.AppendLine($"prefer-oldest = {PreferOldest.ToHocon()}");
if (VerboseDebugLogging is { })
if (VerboseDebugLogging is not null)
sb.AppendLine($"verbose-debug-logging = {VerboseDebugLogging.ToHocon()}");

var durableSb = new StringBuilder();
if (Durable.Keys is { })
if (Durable.Keys is not null)
durableSb.AppendLine($"keys = [{string.Join(",", Durable.Keys.Select(s => s.ToHocon()))}]");

var lmdbSb = new StringBuilder();
var lmdb = Durable.Lmdb;
if (lmdb.Directory is { })
if (lmdb.Directory is not null)
lmdbSb.AppendLine($"dir = {lmdb.Directory.ToHocon()}");
if (lmdb.MapSize is { })
if (lmdb.MapSize is not null)
lmdbSb.AppendLine($"map-size = {lmdb.MapSize}");
if (lmdb.WriteBehindInterval is { })
if (lmdb.WriteBehindInterval is not null)
lmdbSb.AppendLine($"write-behind-interval = {lmdb.WriteBehindInterval.ToHocon()}");

if (lmdbSb.Length > 0)
Expand Down Expand Up @@ -551,18 +560,28 @@ internal static AkkaConfigurationBuilder BuildClusterHocon(
sb.AppendLine("]");
}

if (options.MinimumNumberOfMembers is { })
if (options.MinimumNumberOfMembers is not null)
sb.AppendLine($"min-nr-of-members = {options.MinimumNumberOfMembers}");

if (options.AppVersion is { })
if (options.AppVersion is not null)
sb.AppendLine($"app-version = {options.AppVersion.ToHocon()}");

if (options.LogInfo is { })
if (options.LogInfo is not null)
sb.AppendLine($"log-info = {options.LogInfo.ToHocon()}");

if (options.LogInfoVerbose is { })
if (options.LogInfoVerbose is not null)
sb.AppendLine($"log-info-verbose = {options.LogInfoVerbose.ToHocon()}");

if (options.FailureDetector is not null)
{
var fsb = options.FailureDetector.ToHocon();
if (fsb.Length > 0)
{
sb.AppendLine("failure-detector {\n");
sb.Append(fsb);
sb.AppendLine("}");
}
}
sb.AppendLine("}");

// prepend the composed configuration
Expand Down Expand Up @@ -1080,7 +1099,7 @@ public static AkkaConfigurationBuilder WithSingleton<TKey>(
var clusterSingletonManagerSettings =
ClusterSingletonManagerSettings.Create(system).WithSingletonName(singletonName);

if (options.LeaseImplementation is { })
if (options.LeaseImplementation is not null)
{
var retry = options.LeaseRetryInterval ?? TimeSpan.FromSeconds(5);
clusterSingletonManagerSettings = clusterSingletonManagerSettings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace Akka.Cluster.Hosting
{
public ClusterOptions() { }
public string? AppVersion { get; set; }
public Akka.Remote.Hosting.PhiAccrualFailureDetectorOptions? FailureDetector { get; set; }
public bool? LogInfo { get; set; }
public bool? LogInfoVerbose { get; set; }
public int? MinimumNumberOfMembers { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ namespace Akka.Hosting
{
public static string ToHocon(this bool value) { }
public static string ToHocon(this bool? value) { }
public static string ToHocon(this double value) { }
public static string ToHocon(this double? value) { }
public static string ToHocon(this float value) { }
public static string ToHocon(this float? value) { }
public static string ToHocon(this int value) { }
public static string ToHocon(this int? value) { }
public static string ToHocon(this long value) { }
public static string ToHocon(this long? value) { }
public static string ToHocon(this string? text) { }
public static string ToHocon(this System.TimeSpan value, bool allowInfinite = false, bool zeroIsInfinite = false) { }
public static string ToHocon(this System.TimeSpan? value, bool allowInfinite = false, bool zeroIsInfinite = false) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,39 @@
public static Akka.Hosting.AkkaConfigurationBuilder WithRemoting(this Akka.Hosting.AkkaConfigurationBuilder builder, System.Action<Akka.Remote.Hosting.RemoteOptions> configure) { }
public static Akka.Hosting.AkkaConfigurationBuilder WithRemoting(this Akka.Hosting.AkkaConfigurationBuilder builder, string? hostname = null, int? port = default, string? publicHostname = null, int? publicPort = default) { }
}
public class DeadlineFailureDetectorOptions
{
public DeadlineFailureDetectorOptions() { }
public System.TimeSpan? AcceptableHeartbeatPause { get; set; }
public System.TimeSpan? HeartbeatInterval { get; set; }
public System.Text.StringBuilder ToHocon() { }
}
public class PhiAccrualFailureDetectorOptions
{
public PhiAccrualFailureDetectorOptions() { }
public System.TimeSpan? AcceptableHeartbeatPause { get; set; }
public System.TimeSpan? ExpectedResponseAfter { get; set; }
public System.TimeSpan? HeartbeatInterval { get; set; }
public int? MaxSampleSize { get; set; }
public System.TimeSpan? MinStandardDeviation { get; set; }
public double? Threshold { get; set; }
public System.TimeSpan? UnreachableNodesReaperInterval { get; set; }
public System.Text.StringBuilder ToHocon() { }
}
public class RemoteOptions
{
public RemoteOptions() { }
public bool? EnableSsl { get; set; }
public string? HostName { get; set; }
public long? MaxFrameSize { get; set; }
public int? Port { get; set; }
public string? PublicHostName { get; set; }
public int? PublicPort { get; set; }
public long? ReceiveBufferSize { get; set; }
public long? SendBufferSize { get; set; }
public Akka.Remote.Hosting.SslOptions Ssl { get; set; }
public Akka.Remote.Hosting.DeadlineFailureDetectorOptions? TransportFailureDetector { get; set; }
public Akka.Remote.Hosting.PhiAccrualFailureDetectorOptions? WatchFailureDetector { get; set; }
}
public sealed class SslCertificateOptions
{
Expand Down
48 changes: 48 additions & 0 deletions src/Akka.Hosting/HoconExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,53 @@ public static string ToHocon(this TimeSpan value, bool allowInfinite = false, bo

return value.TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
}

public static string ToHocon(this float? value)
{
if(value is null)
throw new ConfigurationException("Value can not be null");
return ToHocon(value.Value);
}

public static string ToHocon(this float value)
{
return value.ToString(CultureInfo.InvariantCulture);
}

public static string ToHocon(this double? value)
{
if(value is null)
throw new ConfigurationException("Value can not be null");
return ToHocon(value.Value);
}

public static string ToHocon(this double value)
{
return value.ToString(CultureInfo.InvariantCulture);
}

public static string ToHocon(this int? value)
{
if(value is null)
throw new ConfigurationException("Value can not be null");
return ToHocon(value.Value);
}

public static string ToHocon(this int value)
{
return value.ToString(CultureInfo.InvariantCulture);
}

public static string ToHocon(this long? value)
{
if(value is null)
throw new ConfigurationException("Value can not be null");
return ToHocon(value.Value);
}

public static string ToHocon(this long value)
{
return value.ToString(CultureInfo.InvariantCulture);
}
}
}
Loading
Loading