Skip to content

Commit

Permalink
Fix Dns.Resolve issue by using ContinueWith and AggregateException.Fl…
Browse files Browse the repository at this point in the history
…atten (#5260)

* Fix Dns.Resolve issue by using ContinueWith and AggregateException.Flatten

* Capture Sender as a local variable to scope it to local

Co-authored-by: Aaron Stannard <[email protected]>
  • Loading branch information
Arkatufus and Aaronontheweb authored Sep 7, 2021
1 parent 48a704c commit 8a42eda
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 25 deletions.
3 changes: 3 additions & 0 deletions src/core/Akka.API.Tests/CoreAPISpec.ApproveCore.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3294,10 +3294,13 @@ namespace Akka.IO
}
public class Resolved : Akka.IO.Dns.Command
{
public Resolved(string name, System.Exception ex) { }
public Resolved(string name, System.Collections.Generic.IEnumerable<System.Net.IPAddress> ipv4, System.Collections.Generic.IEnumerable<System.Net.IPAddress> ipv6) { }
public System.Net.IPAddress Addr { get; }
public System.Exception Exception { get; }
public System.Collections.Generic.IEnumerable<System.Net.IPAddress> Ipv4 { get; }
public System.Collections.Generic.IEnumerable<System.Net.IPAddress> Ipv6 { get; }
public bool IsSuccess { get; }
public string Name { get; }
public static Akka.IO.Dns.Resolved Create(string name, System.Collections.Generic.IEnumerable<System.Net.IPAddress> addresses) { }
}
Expand Down
14 changes: 14 additions & 0 deletions src/core/Akka.Tests/IO/TcpIntegrationSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
using Xunit.Abstractions;
using FluentAssertions;
using System.Runtime.InteropServices;
using System.Threading;
using Akka.Event;

namespace Akka.Tests.IO
{
Expand Down Expand Up @@ -470,6 +472,18 @@ public void The_TCP_transport_implementation_dont_report_Connected_when_endpoint
replies.Count.ShouldBe(0);
}

[Fact]
public void Should_report_Error_only_once_when_connecting_to_unreachable_DnsEndpoint()
{
var probe = CreateTestProbe();
var endpoint = new DnsEndPoint("fake", 1000);
Sys.Tcp().Tell(new Tcp.Connect(endpoint), probe.Ref);

// expecting CommandFailed or no reply (within timeout)
var replies = probe.ReceiveWhile(TimeSpan.FromSeconds(5), x => x as Tcp.CommandFailed);
replies.Count.ShouldBe(1);
}

[Fact]
public void The_TCP_transport_implementation_handle_tcp_connection_actor_death_properly()
{
Expand Down
30 changes: 22 additions & 8 deletions src/core/Akka/IO/Dns.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.ExceptionServices;
using Akka.Actor;
using Akka.Configuration;
using Akka.Routing;
Expand Down Expand Up @@ -94,6 +96,11 @@ public class Resolved : Command
{
private readonly IPAddress _addr;

public Resolved(string name, Exception ex) : this(name, null, null)
{
Exception = ex;
}

/// <summary>
/// TBD
/// </summary>
Expand All @@ -103,24 +110,28 @@ public class Resolved : Command
public Resolved(string name, IEnumerable<IPAddress> ipv4, IEnumerable<IPAddress> ipv6)
{
Name = name;
Ipv4 = ipv4;
Ipv6 = ipv6;
Ipv4 = ipv4?.ToImmutableList() ?? ImmutableList<IPAddress>.Empty;
Ipv6 = ipv6?.ToImmutableList() ?? ImmutableList<IPAddress>.Empty;

_addr = ipv4.FirstOrDefault() ?? ipv6.FirstOrDefault();
_addr = Ipv4.FirstOrDefault() ?? Ipv6.FirstOrDefault();
}

public bool IsSuccess => Exception == null;

public Exception Exception { get; }

/// <summary>
/// TBD
/// </summary>
public string Name { get; private set; }
public string Name { get; }
/// <summary>
/// TBD
/// </summary>
public IEnumerable<IPAddress> Ipv4 { get; private set; }
public IEnumerable<IPAddress> Ipv4 { get; }
/// <summary>
/// TBD
/// </summary>
public IEnumerable<IPAddress> Ipv6 { get; private set; }
public IEnumerable<IPAddress> Ipv6 { get; }

/// <summary>
/// TBD
Expand All @@ -129,8 +140,11 @@ public IPAddress Addr
{
get
{
//TODO: Throw better exception
if (_addr == null) throw new Exception("Unknown host");
if(Exception != null)
ExceptionDispatchInfo.Capture(Exception).Throw();
else
if (_addr == null) throw new Exception("Unknown host");

return _addr;
}
}
Expand Down
41 changes: 24 additions & 17 deletions src/core/Akka/IO/InetAddressDnsResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.Configuration;

Expand Down Expand Up @@ -43,28 +45,33 @@ public InetAddressDnsResolver(SimpleDnsCache cache, Config config)
/// <returns>TBD</returns>
protected override bool Receive(object message)
{
var resolve = message as Dns.Resolve;
if (resolve != null)
if (message is Dns.Resolve resolve)
{
var replyTo = Sender;
var answer = _cache.Cached(resolve.Name);
if (answer == null)
if (answer != null)
{
try
{
//TODO: IP6
answer = Dns.Resolved.Create(resolve.Name, System.Net.Dns.GetHostEntryAsync(resolve.Name).Result.AddressList.Where(x =>
x.AddressFamily == AddressFamily.InterNetwork
|| _useIpv6 && x.AddressFamily == AddressFamily.InterNetworkV6));
_cache.Put(answer, _positiveTtl);
}
catch (SocketException ex)
replyTo.Tell(answer);
return true;
}

System.Net.Dns.GetHostEntryAsync(resolve.Name).ContinueWith(t =>
{
if (t.IsFaulted)
{
if (ex.SocketErrorCode != SocketError.HostNotFound) throw;
answer = new Dns.Resolved(resolve.Name, Enumerable.Empty<IPAddress>(), Enumerable.Empty<IPAddress>());
_cache.Put(answer, _negativeTtl);
var flattened = t.Exception.Flatten().InnerExceptions;
return flattened.Count == 1
? new Dns.Resolved(resolve.Name, flattened[0])
: new Dns.Resolved(resolve.Name, t.Exception);
}
}
Sender.Tell(answer);
answer = Dns.Resolved.Create(resolve.Name, t.Result.AddressList.Where(x =>
x.AddressFamily == AddressFamily.InterNetwork
|| _useIpv6 && x.AddressFamily == AddressFamily.InterNetworkV6));
_cache.Put(answer, _positiveTtl);
return answer;
}, TaskContinuationOptions.ExecuteSynchronously).PipeTo(replyTo);
return true;
}
return false;
Expand Down

0 comments on commit 8a42eda

Please sign in to comment.