This is an automated email from the ASF dual-hosted git repository.

ptupitsyn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 27b60a58a4 IGNITE-20832 .NET: Improve retry mechanism (#2842)
27b60a58a4 is described below

commit 27b60a58a4c993a2379baabb273e98e1f770b453
Author: Pavel Tupitsyn <ptupit...@apache.org>
AuthorDate: Thu Nov 16 16:07:05 2023 +0200

    IGNITE-20832 .NET: Improve retry mechanism (#2842)
    
    `TestDroppedConnectionIsRestoredOnDemand` was flaky because in some cases 
we failed to retry a broken connection error.
    
    * Close client socket immediately on write error
    * Improve `ShouldRetry` logic
---
 .../dotnet/Apache.Ignite.Tests/ReconnectTests.cs         |  7 ++++++-
 .../Apache.Ignite/Internal/ClientFailoverSocket.cs       |  9 +++++++--
 .../dotnet/Apache.Ignite/Internal/ClientSocket.cs        | 16 +++++++++++++++-
 3 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/ReconnectTests.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/ReconnectTests.cs
index 695377ded0..60767f09fd 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/ReconnectTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/ReconnectTests.cs
@@ -70,8 +70,13 @@ public class ReconnectTests
     [Test]
     public async Task TestDroppedConnectionIsRestoredOnDemand()
     {
+        var cfg = new IgniteClientConfiguration
+        {
+            Logger = new ConsoleLogger { MinLevel = LogLevel.Debug }
+        };
+
         using var server = new FakeServer();
-        using var client = await server.ConnectClientAsync();
+        using var client = await server.ConnectClientAsync(cfg);
 
         Assert.DoesNotThrowAsync(async () => await 
client.Tables.GetTablesAsync());
 
diff --git 
a/modules/platforms/dotnet/Apache.Ignite/Internal/ClientFailoverSocket.cs 
b/modules/platforms/dotnet/Apache.Ignite/Internal/ClientFailoverSocket.cs
index 172bf4a1c8..74a5016bcb 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/ClientFailoverSocket.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/ClientFailoverSocket.cs
@@ -555,14 +555,14 @@ namespace Apache.Ignite.Internal
         {
             var e = exception;
 
-            while (e != null && !(e is SocketException))
+            while (e != null && !IsConnectionError(e))
             {
                 e = e.InnerException;
             }
 
             if (e == null)
             {
-                // Only retry socket exceptions.
+                // Only retry connection errors.
                 return false;
             }
 
@@ -582,6 +582,11 @@ namespace Apache.Ignite.Internal
             var ctx = new RetryPolicyContext(new(Configuration), 
publicOpType.Value, attempt, exception);
 
             return retryPolicy.ShouldRetry(ctx);
+
+            static bool IsConnectionError(Exception e) =>
+                e is SocketException
+                    or IOException
+                    or IgniteClientConnectionException { Code: 
ErrorGroups.Client.Connection };
         }
 
         /// <summary>
diff --git a/modules/platforms/dotnet/Apache.Ignite/Internal/ClientSocket.cs 
b/modules/platforms/dotnet/Apache.Ignite/Internal/ClientSocket.cs
index a0801138b0..dc24fcc5da 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/ClientSocket.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/ClientSocket.cs
@@ -496,7 +496,7 @@ namespace Apache.Ignite.Internal
                 {
                     // Disconnected.
                     throw new IgniteClientConnectionException(
-                        ErrorGroups.Client.Protocol,
+                        ErrorGroups.Client.Connection,
                         "Connection lost (failed to read data from socket)",
                         new SocketException((int) 
SocketError.ConnectionAborted));
                 }
@@ -617,6 +617,10 @@ namespace Apache.Ignite.Internal
                     sslStream.SslProtocol)
                 : null;
 
+        [SuppressMessage(
+            "Microsoft.Design",
+            "CA1031:DoNotCatchGeneralExceptionTypes",
+            Justification = "Any exception during socket write should be 
handled to close the socket.")]
         private async ValueTask SendRequestAsync(PooledArrayBuffer? request, 
ClientOp op, long requestId)
         {
             // Reset heartbeat timer - don't sent heartbeats when connection 
is active anyway.
@@ -664,6 +668,16 @@ namespace Apache.Ignite.Internal
 
                 Metrics.RequestsSent.Add(1);
             }
+            catch (Exception e)
+            {
+                var message = "Exception while writing to socket, connection 
closed: " + e.Message;
+
+                _logger?.Error(e, message);
+                var connEx = new 
IgniteClientConnectionException(ErrorGroups.Client.Connection, message, new 
SocketException());
+
+                Dispose(connEx);
+                throw connEx;
+            }
             finally
             {
                 _sendLock.Release();

Reply via email to