in src/Microsoft.Azure.SignalR.Common/ServiceConnections/ServiceConnectionContainerBase.cs [114:169]
protected ServiceConnectionContainerBase(IServiceConnectionFactory serviceConnectionFactory,
int minConnectionCount,
HubServiceEndpoint endpoint,
IReadOnlyList<IServiceConnection> initialConnections = null,
ILogger logger = null,
AckHandler ackHandler = null)
{
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
ServiceConnectionFactory = serviceConnectionFactory;
Endpoint = endpoint;
// use globally unique AckHanlder if not specified
// It is possible that the multiple MapHub calls the same hub, so that ack messages could be received by another instance of ServiceConnectionContainer
// Use the ack handler singleton to allow ack message to be acked by another container instance
_ackHandler = ackHandler ?? AckHandler.Singleton;
// make sure it is after _endpoint is set
// init initial connections
List<IServiceConnection> initial;
if (initialConnections == null)
{
initial = new List<IServiceConnection>();
}
else
{
initial = new List<IServiceConnection>(initialConnections);
foreach (var conn in initial)
{
conn.ConnectionStatusChanged += OnConnectionStatusChanged;
}
}
var remainingCount = minConnectionCount - (initialConnections?.Count ?? 0);
if (remainingCount > 0)
{
// if still not match or greater than minConnectionCount, create more
var remaining = CreateFixedServiceConnection(remainingCount);
initial.AddRange(remaining);
}
ServiceConnections = initial;
FixedConnectionCount = initial.Count;
ConnectionStatusChanged += OnStatusChanged;
_statusPing = new CustomizedPingTimer(Logger, Constants.CustomizedPingTimer.ServiceStatus, WriteServiceStatusPingAsync, Constants.Periods.DefaultStatusPingInterval, Constants.Periods.DefaultStatusPingInterval);
// when server connection count is specified to 0, the app server only handle negotiate requests
if (initial.Count > 0)
{
_ = StartStatusPing();
}
_serversPing = new CustomizedPingTimer(Logger, Constants.CustomizedPingTimer.Servers, WriteServersPingAsync, Constants.Periods.DefaultServersPingInterval, Constants.Periods.DefaultServersPingInterval);
_partitionedCache = Enumerable.Range(0, 256).ToDictionary(i => (byte)i, i => new StrongBox<WeakReference<IServiceConnection>>(new WeakReference<IServiceConnection>(null)));
}