mirror of
https://github.com/microsoft/autogen.git
synced 2025-11-14 09:03:53 +00:00
Unlike with the InProcessRuntime, there is a two-phase initialization, first when AgentsApp is built (when initial agents are registered) and when it StartAsync()s and connects to the Gateway. Unfortunately, it is possible to attempt to send direct RPC calls to the Gateway before the message channel is opened; in this case, the Gateway has no connected client corresponding to the RPC's clientId, and falls over. The fix is to defer registering agents and subscriptions with the gateway until after the connection is established after .StartAsync() is called.
68 lines
2.0 KiB
C#
68 lines
2.0 KiB
C#
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// FreePortManager.cs
|
|
|
|
using System.Diagnostics;
|
|
|
|
namespace Microsoft.AutoGen.Core.Grpc.Tests;
|
|
|
|
internal sealed class FreePortManager
|
|
{
|
|
private HashSet<int> takenPorts = new();
|
|
private readonly object mutex = new();
|
|
|
|
[DebuggerDisplay($"{{{nameof(Port)}}}")]
|
|
internal sealed class PortTicket(FreePortManager portManager, int port) : IDisposable
|
|
{
|
|
private FreePortManager? portManager = portManager;
|
|
|
|
public int Port { get; } = port;
|
|
|
|
public void Dispose()
|
|
{
|
|
FreePortManager? localPortManager = Interlocked.Exchange(ref this.portManager, null);
|
|
localPortManager?.takenPorts.Remove(this.Port);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return this.Port.ToString();
|
|
}
|
|
|
|
public override bool Equals(object? obj)
|
|
{
|
|
return obj is PortTicket ticket && ticket.Port == this.Port;
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return this.Port.GetHashCode();
|
|
}
|
|
|
|
public static implicit operator int(PortTicket ticket) => ticket.Port;
|
|
public static implicit operator string(PortTicket ticket) => ticket.ToString();
|
|
}
|
|
|
|
public PortTicket GetAvailablePort()
|
|
{
|
|
lock (mutex)
|
|
{
|
|
int port;
|
|
do
|
|
{
|
|
using var listener = new System.Net.Sockets.TcpListener(System.Net.IPAddress.Loopback, 0);
|
|
listener.Start();
|
|
port = ((System.Net.IPEndPoint)listener.LocalEndpoint).Port;
|
|
listener.Stop();
|
|
listener.Dispose();
|
|
Thread.Yield(); // Let the listener actually shut down before we try to use the port
|
|
} while (takenPorts.Contains(port));
|
|
|
|
takenPorts.Add(port);
|
|
|
|
Console.WriteLine($"FreePortManager: Yielding port {port}");
|
|
Debug.WriteLine($"FreePortManager: Yielding port {port}");
|
|
return new PortTicket(this, port);
|
|
}
|
|
}
|
|
}
|