diff --git a/.azure/pipelines/azure-pipelines-external-release.yml b/.azure/pipelines/azure-pipelines-external-release.yml
index 579d1b5239..1a593b40a9 100644
--- a/.azure/pipelines/azure-pipelines-external-release.yml
+++ b/.azure/pipelines/azure-pipelines-external-release.yml
@@ -169,7 +169,7 @@ jobs:
inputs:
action: 'create'
gitHubConnection: ADO_to_Github_ServiceConnection
- tagSource: manual
+ tagSource: userSpecifiedTag
tag: 'v$(Build.BuildNumber)'
title: 'Garnet v$(Build.BuildNumber)'
releaseNotesSource: input
diff --git a/libs/client/GarnetClient.cs b/libs/client/GarnetClient.cs
index 2edabf7627..dcd976a7e6 100644
--- a/libs/client/GarnetClient.cs
+++ b/libs/client/GarnetClient.cs
@@ -188,7 +188,7 @@ public GarnetClient(
///
public void Connect(CancellationToken token = default)
{
- socket = GetSendSocket(timeoutMilliseconds);
+ socket = CreateSendSocket(timeoutMilliseconds);
networkWriter = new NetworkWriter(this, socket, bufferSize, sslOptions, out networkHandler, sendPageSize, networkSendThrottleMax, logger);
networkHandler.StartAsync(sslOptions, $"{address}:{port}", token).ConfigureAwait(false).GetAwaiter().GetResult();
networkSender = networkHandler.GetNetworkSender();
@@ -221,7 +221,7 @@ public void Connect(CancellationToken token = default)
///
public async Task ConnectAsync(CancellationToken token = default)
{
- socket = GetSendSocket(timeoutMilliseconds);
+ socket = CreateSendSocket(timeoutMilliseconds);
networkWriter = new NetworkWriter(this, socket, bufferSize, sslOptions, out networkHandler, sendPageSize, networkSendThrottleMax, logger);
await networkHandler.StartAsync(sslOptions, $"{address}:{port}", token).ConfigureAwait(false);
networkSender = networkHandler.GetNetworkSender();
@@ -249,37 +249,86 @@ public async Task ConnectAsync(CancellationToken token = default)
}
}
- Socket GetSendSocket(int millisecondsTimeout = 0)
+ ///
+ /// Create client send socket
+ ///
+ ///
+ ///
+ ///
+ Socket CreateSendSocket(int millisecondsTimeout = 0)
{
- var ip = IPAddress.Parse(address);
- var endPoint = new IPEndPoint(ip, port);
+ if (!IPAddress.TryParse(address, out var ip))
+ {
+ var hostEntries = Dns.GetHostEntry(address);
+ // Try all available DNS entries if a hostName is provided
+ foreach (var addressEntry in hostEntries.AddressList)
+ {
+ var endPoint = new IPEndPoint(addressEntry, port);
+ if (!TryConnectSocket(endPoint, millisecondsTimeout, out var socket))
+ continue;
+ return socket;
+ }
+
+ // Reaching this point means we failed to establish connection from any of the provided addresses
+ throw new Exception($"Failed to connect at {address}:{port}");
+ }
+ else
+ {
+ var endPoint = new IPEndPoint(ip, port);
+ if (!TryConnectSocket(endPoint, millisecondsTimeout, out var socket))
+ {
+ // If failed here then provided endpoint does not accept connections
+ logger?.LogWarning("Failed to connect at {address}:{port}", ip.ToString(), port);
+ throw new Exception($"Failed to connect at {ip.ToString()}:{port}");
+ }
+ return socket;
+ }
+ }
- var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
+ ///
+ /// Try to establish connection for socket using endPoint
+ ///
+ ///
+ ///
+ ///
+ ///
+ bool TryConnectSocket(IPEndPoint endPoint, int millisecondsTimeout, out Socket socket)
+ {
+ socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
{
NoDelay = true
};
-
- if (millisecondsTimeout > 0)
+ try
{
- var result = socket.BeginConnect(endPoint, null, null);
- result.AsyncWaitHandle.WaitOne(millisecondsTimeout, true);
-
- if (socket.Connected)
+ if (millisecondsTimeout > 0)
{
- socket.EndConnect(result);
+ var result = socket.BeginConnect(endPoint, null, null);
+ result.AsyncWaitHandle.WaitOne(millisecondsTimeout, true);
+
+ if (socket.Connected)
+ {
+ socket.EndConnect(result);
+ }
+ else
+ {
+ socket.Close();
+ throw new Exception($"Failed to connect server {address}:{port}.");
+ }
}
else
{
- socket.Close();
- throw new Exception($"Failed to connect server {address}:{port}.");
+ socket.Connect(endPoint);
}
}
- else
+ catch (Exception ex)
{
- socket.Connect(endPoint);
+ logger?.LogWarning(ex, "Failed at GarnetClient.TryConnectSocket");
+ socket.Dispose();
+ socket = null;
+ return false;
}
- return socket;
+ return true;
}
async Task TimeoutChecker()