From 9b06464d96830e72ee242a8c6d84fca9ef390fa3 Mon Sep 17 00:00:00 2001
From: thefringeninja <495495+thefringeninja@users.noreply.github.com>
Date: Wed, 10 Feb 2021 09:05:02 +0100
Subject: [PATCH 1/5] fixed default keep alive
---
.../EventStoreClientConnectivitySettings.cs | 5 +++--
.../EventStoreClientSettings.ConnectionString.cs | 4 +++-
test/EventStore.Client.Tests/ConnectionStringTests.cs | 2 +-
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/EventStore.Client/EventStoreClientConnectivitySettings.cs b/src/EventStore.Client/EventStoreClientConnectivitySettings.cs
index 3af4ee9ae..7aeb66c2a 100644
--- a/src/EventStore.Client/EventStoreClientConnectivitySettings.cs
+++ b/src/EventStore.Client/EventStoreClientConnectivitySettings.cs
@@ -67,7 +67,7 @@ public class EventStoreClientConnectivitySettings {
///
/// The optional amount of time to wait after which a keepalive ping is sent on the transport.
///
- public TimeSpan? KeepAlive { get; set; }
+ public TimeSpan? KeepAlive { get; set; } = TimeSpan.FromSeconds(10);
///
/// True if pointing to a single EventStoreDB node.
@@ -86,7 +86,8 @@ public class EventStoreClientConnectivitySettings {
MaxDiscoverAttempts = 10,
GossipTimeout = TimeSpan.FromSeconds(5),
DiscoveryInterval = TimeSpan.FromMilliseconds(100),
- NodePreference = NodePreference.Leader
+ NodePreference = NodePreference.Leader,
+ KeepAlive = TimeSpan.FromSeconds(10),
};
}
}
diff --git a/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs b/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs
index 01ab7cdab..340f7bb3e 100644
--- a/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs
+++ b/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs
@@ -167,7 +167,9 @@ private static EventStoreClientSettings CreateSettings(string scheme, (string us
settings.OperationOptions.ThrowOnAppendFailure = (bool)throwOnAppendFailure;
if (typedOptions.TryGetValue(KeepAlive, out var keepAliveMs)) {
- settings.ConnectivitySettings.KeepAlive = TimeSpan.FromMilliseconds((int)keepAliveMs);
+ settings.ConnectivitySettings.KeepAlive = (int)keepAliveMs == -1
+ ? new TimeSpan?()
+ : TimeSpan.FromMilliseconds((int)keepAliveMs);
}
connSettings.Insecure = !useTls;
diff --git a/test/EventStore.Client.Tests/ConnectionStringTests.cs b/test/EventStore.Client.Tests/ConnectionStringTests.cs
index d84d7ae80..ad0b00519 100644
--- a/test/EventStore.Client.Tests/ConnectionStringTests.cs
+++ b/test/EventStore.Client.Tests/ConnectionStringTests.cs
@@ -144,7 +144,7 @@ public void with_valid_single_node_connection_string() {
Assert.Equal(330, settings.OperationOptions.TimeoutAfter.Value.TotalMilliseconds);
Assert.False(settings.OperationOptions.ThrowOnAppendFailure);
- settings = EventStoreClientSettings.Create("esdb://hostname:4321/?tls=false");
+ settings = EventStoreClientSettings.Create("esdb://hostname:4321/?tls=false&keepAlive=-1");
Assert.Null(settings.DefaultCredentials);
Assert.Equal("http://hostname:4321/", settings.ConnectivitySettings.Address.ToString());
Assert.Empty(settings.ConnectivitySettings.GossipSeeds);
From 845a7c766de71c09b13aa677952e192e9dc1516a Mon Sep 17 00:00:00 2001
From: thefringeninja <495495+thefringeninja@users.noreply.github.com>
Date: Wed, 10 Feb 2021 10:54:30 +0100
Subject: [PATCH 2/5] renamed keepAlive -> keepAliveInterval
---
src/EventStore.Client/ChannelFactory.cs | 8 +++---
.../EventStoreClientConnectivitySettings.cs | 4 +--
...entStoreClientSettings.ConnectionString.cs | 16 +++++++-----
.../ConnectionStringTests.cs | 26 +++++++++----------
4 files changed, 28 insertions(+), 26 deletions(-)
diff --git a/src/EventStore.Client/ChannelFactory.cs b/src/EventStore.Client/ChannelFactory.cs
index dfbbbf8a3..88b93fe85 100644
--- a/src/EventStore.Client/ChannelFactory.cs
+++ b/src/EventStore.Client/ChannelFactory.cs
@@ -41,8 +41,8 @@ HttpMessageHandler CreateHandler() {
}
var handler = new SocketsHttpHandler();
- if (settings.ConnectivitySettings.KeepAlive.HasValue) {
- handler.KeepAlivePingDelay = settings.ConnectivitySettings.KeepAlive.Value;
+ if (settings.ConnectivitySettings.KeepAliveInterval.HasValue) {
+ handler.KeepAlivePingDelay = settings.ConnectivitySettings.KeepAliveInterval.Value;
}
return handler;
@@ -52,9 +52,9 @@ HttpMessageHandler CreateHandler() {
GetChannelOptions());
IEnumerable GetChannelOptions() {
- if (settings.ConnectivitySettings.KeepAlive.HasValue) {
+ if (settings.ConnectivitySettings.KeepAliveInterval.HasValue) {
yield return new ChannelOption("grpc.keepalive_time_ms",
- (int)settings.ConnectivitySettings.KeepAlive.Value.TotalMilliseconds);
+ (int)settings.ConnectivitySettings.KeepAliveInterval.Value.TotalMilliseconds);
}
}
#endif
diff --git a/src/EventStore.Client/EventStoreClientConnectivitySettings.cs b/src/EventStore.Client/EventStoreClientConnectivitySettings.cs
index 7aeb66c2a..c8f22aaaf 100644
--- a/src/EventStore.Client/EventStoreClientConnectivitySettings.cs
+++ b/src/EventStore.Client/EventStoreClientConnectivitySettings.cs
@@ -67,7 +67,7 @@ public class EventStoreClientConnectivitySettings {
///
/// The optional amount of time to wait after which a keepalive ping is sent on the transport.
///
- public TimeSpan? KeepAlive { get; set; } = TimeSpan.FromSeconds(10);
+ public TimeSpan? KeepAliveInterval { get; set; } = TimeSpan.FromSeconds(10);
///
/// True if pointing to a single EventStoreDB node.
@@ -87,7 +87,7 @@ public class EventStoreClientConnectivitySettings {
GossipTimeout = TimeSpan.FromSeconds(5),
DiscoveryInterval = TimeSpan.FromMilliseconds(100),
NodePreference = NodePreference.Leader,
- KeepAlive = TimeSpan.FromSeconds(10),
+ KeepAliveInterval = TimeSpan.FromSeconds(10),
};
}
}
diff --git a/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs b/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs
index 340f7bb3e..0b30709c6 100644
--- a/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs
+++ b/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs
@@ -35,7 +35,8 @@ private static class ConnectionStringParser {
private const string TlsVerifyCert = nameof(TlsVerifyCert);
private const string OperationTimeout = nameof(OperationTimeout);
private const string ThrowOnAppendFailure = nameof(ThrowOnAppendFailure);
- private const string KeepAlive = nameof(KeepAlive);
+ private const string KeepAliveInterval = nameof(KeepAliveInterval);
+ private const string KeepAliveTimeout = nameof(KeepAliveTimeout);
private const string UriSchemeDiscover = "esdb+discover";
@@ -54,7 +55,8 @@ private static class ConnectionStringParser {
{TlsVerifyCert, typeof(bool)},
{OperationTimeout, typeof(int)},
{ThrowOnAppendFailure, typeof(bool)},
- {KeepAlive, typeof(int)}
+ {KeepAliveInterval, typeof(int)},
+ {KeepAliveTimeout, typeof(int)},
};
public static EventStoreClientSettings Parse(string connectionString) {
@@ -166,10 +168,10 @@ private static EventStoreClientSettings CreateSettings(string scheme, (string us
if (typedOptions.TryGetValue(ThrowOnAppendFailure, out object throwOnAppendFailure))
settings.OperationOptions.ThrowOnAppendFailure = (bool)throwOnAppendFailure;
- if (typedOptions.TryGetValue(KeepAlive, out var keepAliveMs)) {
- settings.ConnectivitySettings.KeepAlive = (int)keepAliveMs == -1
+ if (typedOptions.TryGetValue(KeepAliveInterval, out var keepAliveIntervalMs)) {
+ settings.ConnectivitySettings.KeepAliveInterval = (int)keepAliveIntervalMs == -1
? new TimeSpan?()
- : TimeSpan.FromMilliseconds((int)keepAliveMs);
+ : TimeSpan.FromMilliseconds((int)keepAliveIntervalMs);
}
connSettings.Insecure = !useTls;
@@ -192,8 +194,8 @@ private static EventStoreClientSettings CreateSettings(string scheme, (string us
handler.SslOptions.RemoteCertificateValidationCallback = delegate { return true; };
}
- if (settings.ConnectivitySettings.KeepAlive.HasValue) {
- handler.KeepAlivePingDelay = settings.ConnectivitySettings.KeepAlive.Value;
+ if (settings.ConnectivitySettings.KeepAliveInterval.HasValue) {
+ handler.KeepAlivePingDelay = settings.ConnectivitySettings.KeepAliveInterval.Value;
}
return handler;
diff --git a/test/EventStore.Client.Tests/ConnectionStringTests.cs b/test/EventStore.Client.Tests/ConnectionStringTests.cs
index ad0b00519..f388ac122 100644
--- a/test/EventStore.Client.Tests/ConnectionStringTests.cs
+++ b/test/EventStore.Client.Tests/ConnectionStringTests.cs
@@ -90,7 +90,7 @@ public void connection_string_with_duplicate_key_should_throw(string connectionS
InlineData("esdb://user:pass@127.0.0.1/?gossipTimeout=defg"),
InlineData("esdb://user:pass@127.0.0.1/?tlsVerifyCert=truee"),
InlineData("esdb://user:pass@127.0.0.1/?nodePreference=blabla"),
- InlineData("esdb://user:pass@127.0.0.1/?keepAlive=blabla")]
+ InlineData("esdb://user:pass@127.0.0.1/?keepAliveInterval=blabla")]
public void connection_string_with_invalid_settings_should_throw(string connectionString) {
Assert.Throws(() => EventStoreClientSettings.Create(connectionString));
}
@@ -109,7 +109,7 @@ public void with_different_node_preferences(string nodePreference, NodePreferenc
[Fact]
public void with_valid_single_node_connection_string() {
var settings = EventStoreClientSettings.Create(
- "esdb://user:pass@127.0.0.1/?maxDiscoverAttempts=13&DiscoveryInterval=37&gossipTimeout=33&nOdEPrEfErence=FoLLoWer&tlsVerifyCert=false&keepAlive=10");
+ "esdb://user:pass@127.0.0.1/?maxDiscoverAttempts=13&DiscoveryInterval=37&gossipTimeout=33&nOdEPrEfErence=FoLLoWer&tlsVerifyCert=false&keepAliveInterval=10");
Assert.Equal("user", settings.DefaultCredentials.Username);
Assert.Equal("pass", settings.DefaultCredentials.Password);
Assert.Equal("https://127.0.0.1:2113/", settings.ConnectivitySettings.Address.ToString());
@@ -120,12 +120,12 @@ public void with_valid_single_node_connection_string() {
Assert.Equal(37, settings.ConnectivitySettings.DiscoveryInterval.TotalMilliseconds);
Assert.Equal(33, settings.ConnectivitySettings.GossipTimeout.TotalMilliseconds);
Assert.Equal(NodePreference.Follower, settings.ConnectivitySettings.NodePreference);
- Assert.Equal(TimeSpan.FromMilliseconds(10), settings.ConnectivitySettings.KeepAlive);
+ Assert.Equal(TimeSpan.FromMilliseconds(10), settings.ConnectivitySettings.KeepAliveInterval);
#if !GRPC_CORE
Assert.NotNull(settings.CreateHttpMessageHandler);
#endif
settings = EventStoreClientSettings.Create(
- "esdb://127.0.0.1?connectionName=test&maxDiscoverAttempts=13&DiscoveryInterval=37&nOdEPrEfErence=FoLLoWer&tls=true&tlsVerifyCert=true&operationTimeout=330&throwOnAppendFailure=faLse&KEepAlive=10");
+ "esdb://127.0.0.1?connectionName=test&maxDiscoverAttempts=13&DiscoveryInterval=37&nOdEPrEfErence=FoLLoWer&tls=true&tlsVerifyCert=true&operationTimeout=330&throwOnAppendFailure=faLse&KEepAliveInTeRvAl=10");
Assert.Null(settings.DefaultCredentials);
Assert.Equal("test", settings.ConnectionName);
Assert.Equal("https://127.0.0.1:2113/", settings.ConnectivitySettings.Address.ToString());
@@ -136,7 +136,7 @@ public void with_valid_single_node_connection_string() {
Assert.Equal(13, settings.ConnectivitySettings.MaxDiscoverAttempts);
Assert.Equal(37, settings.ConnectivitySettings.DiscoveryInterval.TotalMilliseconds);
Assert.Equal(NodePreference.Follower, settings.ConnectivitySettings.NodePreference);
- Assert.Equal(TimeSpan.FromMilliseconds(10), settings.ConnectivitySettings.KeepAlive);
+ Assert.Equal(TimeSpan.FromMilliseconds(10), settings.ConnectivitySettings.KeepAliveInterval);
#if !GRPC_CORE
Assert.NotNull(settings.CreateHttpMessageHandler);
#endif
@@ -144,14 +144,14 @@ public void with_valid_single_node_connection_string() {
Assert.Equal(330, settings.OperationOptions.TimeoutAfter.Value.TotalMilliseconds);
Assert.False(settings.OperationOptions.ThrowOnAppendFailure);
- settings = EventStoreClientSettings.Create("esdb://hostname:4321/?tls=false&keepAlive=-1");
+ settings = EventStoreClientSettings.Create("esdb://hostname:4321/?tls=false&keepAliveInterval=-1");
Assert.Null(settings.DefaultCredentials);
Assert.Equal("http://hostname:4321/", settings.ConnectivitySettings.Address.ToString());
Assert.Empty(settings.ConnectivitySettings.GossipSeeds);
Assert.Null(settings.ConnectivitySettings.IpGossipSeeds);
Assert.Null(settings.ConnectivitySettings.DnsGossipSeeds);
Assert.True(settings.ConnectivitySettings.Insecure);
- Assert.Null(settings.ConnectivitySettings.KeepAlive);
+ Assert.Null(settings.ConnectivitySettings.KeepAliveInterval);
#if !GRPC_CORE
Assert.NotNull(settings.CreateHttpMessageHandler);
#endif
@@ -181,14 +181,14 @@ public void with_default_settings() {
settings.OperationOptions.TimeoutAfter!.Value.TotalMilliseconds);
Assert.Equal(EventStoreClientOperationOptions.Default.ThrowOnAppendFailure,
settings.OperationOptions.ThrowOnAppendFailure);
- Assert.Equal(EventStoreClientConnectivitySettings.Default.KeepAlive,
- settings.ConnectivitySettings.KeepAlive);
+ Assert.Equal(EventStoreClientConnectivitySettings.Default.KeepAliveInterval,
+ settings.ConnectivitySettings.KeepAliveInterval);
}
[Fact]
public void with_valid_cluster_connection_string() {
var settings = EventStoreClientSettings.Create(
- "esdb://user:pass@127.0.0.1,127.0.0.2:3321,127.0.0.3/?maxDiscoverAttempts=13&DiscoveryInterval=37&nOdEPrEfErence=FoLLoWer&tlsVerifyCert=false&KEepAlive=10");
+ "esdb://user:pass@127.0.0.1,127.0.0.2:3321,127.0.0.3/?maxDiscoverAttempts=13&DiscoveryInterval=37&nOdEPrEfErence=FoLLoWer&tlsVerifyCert=false&KEepAliveInTeRVAl=10");
Assert.Equal("user", settings.DefaultCredentials.Username);
Assert.Equal("pass", settings.DefaultCredentials.Password);
Assert.NotEmpty(settings.ConnectivitySettings.GossipSeeds);
@@ -205,14 +205,14 @@ public void with_valid_cluster_connection_string() {
Assert.Equal(13, settings.ConnectivitySettings.MaxDiscoverAttempts);
Assert.Equal(37, settings.ConnectivitySettings.DiscoveryInterval.TotalMilliseconds);
Assert.Equal(NodePreference.Follower, settings.ConnectivitySettings.NodePreference);
- Assert.Equal(TimeSpan.FromMilliseconds(10), settings.ConnectivitySettings.KeepAlive);
+ Assert.Equal(TimeSpan.FromMilliseconds(10), settings.ConnectivitySettings.KeepAliveInterval);
#if !GRPC_CORE
Assert.NotNull(settings.CreateHttpMessageHandler);
#endif
settings = EventStoreClientSettings.Create(
- "esdb://user:pass@host1,host2:3321,127.0.0.3/?tls=false&maxDiscoverAttempts=13&DiscoveryInterval=37&nOdEPrEfErence=FoLLoWer&tlsVerifyCert=false&KEepAlive=10");
+ "esdb://user:pass@host1,host2:3321,127.0.0.3/?tls=false&maxDiscoverAttempts=13&DiscoveryInterval=37&nOdEPrEfErence=FoLLoWer&tlsVerifyCert=false&KEepAliveInTeRvAl=10");
Assert.Equal("user", settings.DefaultCredentials.Username);
Assert.Equal("pass", settings.DefaultCredentials.Password);
Assert.NotEmpty(settings.ConnectivitySettings.GossipSeeds);
@@ -229,7 +229,7 @@ public void with_valid_cluster_connection_string() {
Assert.Equal(13, settings.ConnectivitySettings.MaxDiscoverAttempts);
Assert.Equal(37, settings.ConnectivitySettings.DiscoveryInterval.TotalMilliseconds);
Assert.Equal(NodePreference.Follower, settings.ConnectivitySettings.NodePreference);
- Assert.Equal(TimeSpan.FromMilliseconds(10), settings.ConnectivitySettings.KeepAlive);
+ Assert.Equal(TimeSpan.FromMilliseconds(10), settings.ConnectivitySettings.KeepAliveInterval);
#if !GRPC_CORE
Assert.NotNull(settings.CreateHttpMessageHandler);
#endif
From fd122729d5fda11cc473156cd16a27055087204d Mon Sep 17 00:00:00 2001
From: thefringeninja <495495+thefringeninja@users.noreply.github.com>
Date: Thu, 11 Feb 2021 11:52:44 +0100
Subject: [PATCH 3/5] add keepalivetimeout to connection string
---
src/EventStore.Client/ChannelFactory.cs | 24 ++++++++++-------
.../EventStoreClientConnectivitySettings.cs | 8 +++++-
...entStoreClientSettings.ConnectionString.cs | 26 +++++++++++++------
.../ConnectionStringTests.cs | 23 +++++++++++-----
4 files changed, 55 insertions(+), 26 deletions(-)
diff --git a/src/EventStore.Client/ChannelFactory.cs b/src/EventStore.Client/ChannelFactory.cs
index 88b93fe85..812ce28bd 100644
--- a/src/EventStore.Client/ChannelFactory.cs
+++ b/src/EventStore.Client/ChannelFactory.cs
@@ -40,23 +40,27 @@ HttpMessageHandler CreateHandler() {
return settings.CreateHttpMessageHandler.Invoke();
}
- var handler = new SocketsHttpHandler();
- if (settings.ConnectivitySettings.KeepAliveInterval.HasValue) {
- handler.KeepAlivePingDelay = settings.ConnectivitySettings.KeepAliveInterval.Value;
- }
-
- return handler;
+ return new SocketsHttpHandler {
+ KeepAlivePingDelay = settings.ConnectivitySettings.KeepAliveInterval,
+ KeepAlivePingTimeout = settings.ConnectivitySettings.KeepAliveTimeout
+ };
}
#else
return new Channel(address.Host, address.Port, settings.ChannelCredentials ?? ChannelCredentials.Insecure,
GetChannelOptions());
IEnumerable GetChannelOptions() {
- if (settings.ConnectivitySettings.KeepAliveInterval.HasValue) {
- yield return new ChannelOption("grpc.keepalive_time_ms",
- (int)settings.ConnectivitySettings.KeepAliveInterval.Value.TotalMilliseconds);
- }
+ yield return new ChannelOption("grpc.keepalive_time_ms",
+ GetValue((int)settings.ConnectivitySettings.KeepAliveInterval.TotalMilliseconds));
+
+ yield return new ChannelOption("grpc.keepalive_timeout_ms",
+ GetValue((int)settings.ConnectivitySettings.KeepAliveTimeout.TotalMilliseconds));
}
+
+ static int GetValue(int value) => value switch {
+ { } v when v < 0 => int.MaxValue,
+ _ => value
+ };
#endif
}
}
diff --git a/src/EventStore.Client/EventStoreClientConnectivitySettings.cs b/src/EventStore.Client/EventStoreClientConnectivitySettings.cs
index c8f22aaaf..c520935c9 100644
--- a/src/EventStore.Client/EventStoreClientConnectivitySettings.cs
+++ b/src/EventStore.Client/EventStoreClientConnectivitySettings.cs
@@ -67,7 +67,12 @@ public class EventStoreClientConnectivitySettings {
///
/// The optional amount of time to wait after which a keepalive ping is sent on the transport.
///
- public TimeSpan? KeepAliveInterval { get; set; } = TimeSpan.FromSeconds(10);
+ public TimeSpan KeepAliveInterval { get; set; } = TimeSpan.FromSeconds(10);
+
+ ///
+ /// The optional amount of time to wait after which a sent keepalive ping is considered timed out.
+ ///
+ public TimeSpan KeepAliveTimeout { get; set; } = TimeSpan.FromSeconds(10);
///
/// True if pointing to a single EventStoreDB node.
@@ -88,6 +93,7 @@ public class EventStoreClientConnectivitySettings {
DiscoveryInterval = TimeSpan.FromMilliseconds(100),
NodePreference = NodePreference.Leader,
KeepAliveInterval = TimeSpan.FromSeconds(10),
+ KeepAliveTimeout = TimeSpan.FromSeconds(10),
};
}
}
diff --git a/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs b/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs
index 0b30709c6..937e3fe28 100644
--- a/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs
+++ b/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
+using System.Threading;
#if !GRPC_CORE
using System.Net.Http;
#endif
@@ -169,9 +170,19 @@ private static EventStoreClientSettings CreateSettings(string scheme, (string us
settings.OperationOptions.ThrowOnAppendFailure = (bool)throwOnAppendFailure;
if (typedOptions.TryGetValue(KeepAliveInterval, out var keepAliveIntervalMs)) {
- settings.ConnectivitySettings.KeepAliveInterval = (int)keepAliveIntervalMs == -1
- ? new TimeSpan?()
- : TimeSpan.FromMilliseconds((int)keepAliveIntervalMs);
+ settings.ConnectivitySettings.KeepAliveInterval = keepAliveIntervalMs switch {
+ int value when value == -1 => Timeout.InfiniteTimeSpan,
+ int value when value >= 0 => TimeSpan.FromMilliseconds(value),
+ _ => throw new InvalidSettingException($"Invalid KeepAliveInterval: {keepAliveIntervalMs}")
+ };
+ }
+
+ if (typedOptions.TryGetValue(KeepAliveTimeout, out var keepAliveTimeoutMs)) {
+ settings.ConnectivitySettings.KeepAliveTimeout = keepAliveTimeoutMs switch {
+ int value when value == -1 => Timeout.InfiniteTimeSpan,
+ int value when value >= 0 => TimeSpan.FromMilliseconds(value),
+ _ => throw new InvalidSettingException($"Invalid KeepAliveTimeout: {keepAliveTimeoutMs}")
+ };
}
connSettings.Insecure = !useTls;
@@ -188,16 +199,15 @@ private static EventStoreClientSettings CreateSettings(string scheme, (string us
#if !GRPC_CORE
settings.CreateHttpMessageHandler = () => {
- var handler = new SocketsHttpHandler();
+ var handler = new SocketsHttpHandler {
+ KeepAlivePingDelay = settings.ConnectivitySettings.KeepAliveInterval,
+ KeepAlivePingTimeout = settings.ConnectivitySettings.KeepAliveTimeout
+ };
if (typedOptions.TryGetValue(TlsVerifyCert, out var tlsVerifyCert) && !(bool)tlsVerifyCert) {
handler.SslOptions.RemoteCertificateValidationCallback = delegate { return true; };
}
- if (settings.ConnectivitySettings.KeepAliveInterval.HasValue) {
- handler.KeepAlivePingDelay = settings.ConnectivitySettings.KeepAliveInterval.Value;
- }
-
return handler;
};
#endif
diff --git a/test/EventStore.Client.Tests/ConnectionStringTests.cs b/test/EventStore.Client.Tests/ConnectionStringTests.cs
index f388ac122..b740bafd6 100644
--- a/test/EventStore.Client.Tests/ConnectionStringTests.cs
+++ b/test/EventStore.Client.Tests/ConnectionStringTests.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Net;
+using System.Threading;
using Xunit;
namespace EventStore.Client {
@@ -90,7 +91,8 @@ public void connection_string_with_duplicate_key_should_throw(string connectionS
InlineData("esdb://user:pass@127.0.0.1/?gossipTimeout=defg"),
InlineData("esdb://user:pass@127.0.0.1/?tlsVerifyCert=truee"),
InlineData("esdb://user:pass@127.0.0.1/?nodePreference=blabla"),
- InlineData("esdb://user:pass@127.0.0.1/?keepAliveInterval=blabla")]
+ InlineData("esdb://user:pass@127.0.0.1/?keepAliveInterval=blabla"),
+ InlineData("esdb://user:pass@127.0.0.1/?keepAliveTimeout=blabla")]
public void connection_string_with_invalid_settings_should_throw(string connectionString) {
Assert.Throws(() => EventStoreClientSettings.Create(connectionString));
}
@@ -109,7 +111,7 @@ public void with_different_node_preferences(string nodePreference, NodePreferenc
[Fact]
public void with_valid_single_node_connection_string() {
var settings = EventStoreClientSettings.Create(
- "esdb://user:pass@127.0.0.1/?maxDiscoverAttempts=13&DiscoveryInterval=37&gossipTimeout=33&nOdEPrEfErence=FoLLoWer&tlsVerifyCert=false&keepAliveInterval=10");
+ "esdb://user:pass@127.0.0.1/?maxDiscoverAttempts=13&DiscoveryInterval=37&gossipTimeout=33&nOdEPrEfErence=FoLLoWer&tlsVerifyCert=false&keepAliveInterval=10&keepAliveTimeout=2000");
Assert.Equal("user", settings.DefaultCredentials.Username);
Assert.Equal("pass", settings.DefaultCredentials.Password);
Assert.Equal("https://127.0.0.1:2113/", settings.ConnectivitySettings.Address.ToString());
@@ -121,11 +123,12 @@ public void with_valid_single_node_connection_string() {
Assert.Equal(33, settings.ConnectivitySettings.GossipTimeout.TotalMilliseconds);
Assert.Equal(NodePreference.Follower, settings.ConnectivitySettings.NodePreference);
Assert.Equal(TimeSpan.FromMilliseconds(10), settings.ConnectivitySettings.KeepAliveInterval);
+ Assert.Equal(TimeSpan.FromSeconds(2), settings.ConnectivitySettings.KeepAliveTimeout);
#if !GRPC_CORE
Assert.NotNull(settings.CreateHttpMessageHandler);
#endif
settings = EventStoreClientSettings.Create(
- "esdb://127.0.0.1?connectionName=test&maxDiscoverAttempts=13&DiscoveryInterval=37&nOdEPrEfErence=FoLLoWer&tls=true&tlsVerifyCert=true&operationTimeout=330&throwOnAppendFailure=faLse&KEepAliveInTeRvAl=10");
+ "esdb://127.0.0.1?connectionName=test&maxDiscoverAttempts=13&DiscoveryInterval=37&nOdEPrEfErence=FoLLoWer&tls=true&tlsVerifyCert=true&operationTimeout=330&throwOnAppendFailure=faLse&KEepAliveInTeRvAl=10&KeEpAlIvEtImEoUt=2000");
Assert.Null(settings.DefaultCredentials);
Assert.Equal("test", settings.ConnectionName);
Assert.Equal("https://127.0.0.1:2113/", settings.ConnectivitySettings.Address.ToString());
@@ -137,6 +140,7 @@ public void with_valid_single_node_connection_string() {
Assert.Equal(37, settings.ConnectivitySettings.DiscoveryInterval.TotalMilliseconds);
Assert.Equal(NodePreference.Follower, settings.ConnectivitySettings.NodePreference);
Assert.Equal(TimeSpan.FromMilliseconds(10), settings.ConnectivitySettings.KeepAliveInterval);
+ Assert.Equal(TimeSpan.FromSeconds(2), settings.ConnectivitySettings.KeepAliveTimeout);
#if !GRPC_CORE
Assert.NotNull(settings.CreateHttpMessageHandler);
#endif
@@ -144,14 +148,15 @@ public void with_valid_single_node_connection_string() {
Assert.Equal(330, settings.OperationOptions.TimeoutAfter.Value.TotalMilliseconds);
Assert.False(settings.OperationOptions.ThrowOnAppendFailure);
- settings = EventStoreClientSettings.Create("esdb://hostname:4321/?tls=false&keepAliveInterval=-1");
+ settings = EventStoreClientSettings.Create("esdb://hostname:4321/?tls=false&keepAliveInterval=-1&keepAliveTimeout=-1");
Assert.Null(settings.DefaultCredentials);
Assert.Equal("http://hostname:4321/", settings.ConnectivitySettings.Address.ToString());
Assert.Empty(settings.ConnectivitySettings.GossipSeeds);
Assert.Null(settings.ConnectivitySettings.IpGossipSeeds);
Assert.Null(settings.ConnectivitySettings.DnsGossipSeeds);
Assert.True(settings.ConnectivitySettings.Insecure);
- Assert.Null(settings.ConnectivitySettings.KeepAliveInterval);
+ Assert.Equal(Timeout.InfiniteTimeSpan, settings.ConnectivitySettings.KeepAliveInterval);
+ Assert.Equal(Timeout.InfiniteTimeSpan, settings.ConnectivitySettings.KeepAliveTimeout);
#if !GRPC_CORE
Assert.NotNull(settings.CreateHttpMessageHandler);
#endif
@@ -183,12 +188,14 @@ public void with_default_settings() {
settings.OperationOptions.ThrowOnAppendFailure);
Assert.Equal(EventStoreClientConnectivitySettings.Default.KeepAliveInterval,
settings.ConnectivitySettings.KeepAliveInterval);
+ Assert.Equal(EventStoreClientConnectivitySettings.Default.KeepAliveTimeout,
+ settings.ConnectivitySettings.KeepAliveTimeout);
}
[Fact]
public void with_valid_cluster_connection_string() {
var settings = EventStoreClientSettings.Create(
- "esdb://user:pass@127.0.0.1,127.0.0.2:3321,127.0.0.3/?maxDiscoverAttempts=13&DiscoveryInterval=37&nOdEPrEfErence=FoLLoWer&tlsVerifyCert=false&KEepAliveInTeRVAl=10");
+ "esdb://user:pass@127.0.0.1,127.0.0.2:3321,127.0.0.3/?maxDiscoverAttempts=13&DiscoveryInterval=37&nOdEPrEfErence=FoLLoWer&tlsVerifyCert=false&KEepAliveInTeRVAl=10&KeEpAlIvEtImEoUt=2000");
Assert.Equal("user", settings.DefaultCredentials.Username);
Assert.Equal("pass", settings.DefaultCredentials.Password);
Assert.NotEmpty(settings.ConnectivitySettings.GossipSeeds);
@@ -206,13 +213,14 @@ public void with_valid_cluster_connection_string() {
Assert.Equal(37, settings.ConnectivitySettings.DiscoveryInterval.TotalMilliseconds);
Assert.Equal(NodePreference.Follower, settings.ConnectivitySettings.NodePreference);
Assert.Equal(TimeSpan.FromMilliseconds(10), settings.ConnectivitySettings.KeepAliveInterval);
+ Assert.Equal(TimeSpan.FromSeconds(2), settings.ConnectivitySettings.KeepAliveTimeout);
#if !GRPC_CORE
Assert.NotNull(settings.CreateHttpMessageHandler);
#endif
settings = EventStoreClientSettings.Create(
- "esdb://user:pass@host1,host2:3321,127.0.0.3/?tls=false&maxDiscoverAttempts=13&DiscoveryInterval=37&nOdEPrEfErence=FoLLoWer&tlsVerifyCert=false&KEepAliveInTeRvAl=10");
+ "esdb://user:pass@host1,host2:3321,127.0.0.3/?tls=false&maxDiscoverAttempts=13&DiscoveryInterval=37&nOdEPrEfErence=FoLLoWer&tlsVerifyCert=false&KEepAliveInTeRvAl=10&KeEpAlIvEtImEoUt=2000");
Assert.Equal("user", settings.DefaultCredentials.Username);
Assert.Equal("pass", settings.DefaultCredentials.Password);
Assert.NotEmpty(settings.ConnectivitySettings.GossipSeeds);
@@ -230,6 +238,7 @@ public void with_valid_cluster_connection_string() {
Assert.Equal(37, settings.ConnectivitySettings.DiscoveryInterval.TotalMilliseconds);
Assert.Equal(NodePreference.Follower, settings.ConnectivitySettings.NodePreference);
Assert.Equal(TimeSpan.FromMilliseconds(10), settings.ConnectivitySettings.KeepAliveInterval);
+ Assert.Equal(TimeSpan.FromSeconds(2), settings.ConnectivitySettings.KeepAliveTimeout);
#if !GRPC_CORE
Assert.NotNull(settings.CreateHttpMessageHandler);
#endif
From 8f8cffd70a17686d294e748faeadba8cc8b37e61 Mon Sep 17 00:00:00 2001
From: thefringeninja <495495+thefringeninja@users.noreply.github.com>
Date: Mon, 15 Feb 2021 13:05:57 +0100
Subject: [PATCH 4/5] add warning when keep alive interval exceeds minimum
---
src/EventStore.Client/MultiChannel.cs | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/EventStore.Client/MultiChannel.cs b/src/EventStore.Client/MultiChannel.cs
index c3881c0a4..5e036b1d5 100644
--- a/src/EventStore.Client/MultiChannel.cs
+++ b/src/EventStore.Client/MultiChannel.cs
@@ -4,6 +4,8 @@
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
#nullable enable
namespace EventStore.Client {
@@ -11,9 +13,9 @@ internal class MultiChannel : IDisposable, IAsyncDisposable {
private readonly EventStoreClientSettings _settings;
private readonly IEndpointDiscoverer _endpointDiscoverer;
private readonly ConcurrentDictionary _channels;
+ private readonly ILogger _log;
private EndPoint? _current;
-
private int _disposed;
public MultiChannel(EventStoreClientSettings settings) {
@@ -22,6 +24,12 @@ public MultiChannel(EventStoreClientSettings settings) {
? (IEndpointDiscoverer)new SingleNodeEndpointDiscoverer(settings.ConnectivitySettings.Address)
: new GossipBasedEndpointDiscoverer(settings.ConnectivitySettings, new GrpcGossipClient(settings));
_channels = new ConcurrentDictionary();
+ _log = settings.LoggerFactory?.CreateLogger() ?? new NullLogger();
+
+ if (settings.ConnectivitySettings.KeepAliveInterval < TimeSpan.FromSeconds(10)) {
+ _log.LogWarning("Specified KeepAliveInterval of {interval} is less than recommended 10_000 ms.",
+ settings.ConnectivitySettings.KeepAliveInterval);
+ }
}
public void SetEndPoint(EndPoint value) => _current = value;
From a6e403a6fa3cf91767a9c846006830133e7b281a Mon Sep 17 00:00:00 2001
From: thefringeninja <495495+thefringeninja@users.noreply.github.com>
Date: Wed, 17 Feb 2021 11:10:04 +0100
Subject: [PATCH 5/5] refactored tests
---
test/Directory.Build.props | 1 +
.../ConnectionStringTests.cs | 432 ++++++++++--------
2 files changed, 244 insertions(+), 189 deletions(-)
diff --git a/test/Directory.Build.props b/test/Directory.Build.props
index 467d205d3..1d09bfb7c 100644
--- a/test/Directory.Build.props
+++ b/test/Directory.Build.props
@@ -1,6 +1,7 @@
+
diff --git a/test/EventStore.Client.Tests/ConnectionStringTests.cs b/test/EventStore.Client.Tests/ConnectionStringTests.cs
index b740bafd6..d36357507 100644
--- a/test/EventStore.Client.Tests/ConnectionStringTests.cs
+++ b/test/EventStore.Client.Tests/ConnectionStringTests.cs
@@ -1,11 +1,145 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Net;
using System.Threading;
+#if !GRPC_CORE
+using System.Net.Http;
+#endif
+using AutoFixture;
using Xunit;
namespace EventStore.Client {
public class ConnectionStringTests {
+ public static IEnumerable