Exemple #1
0
        private async ValueTask <Connection> GetConnectionAsync(SiloAddress endpoint)
        {
            ImmutableArray <Connection> result;
            ConnectionEntry             entry = default;
            var acquiredConnectionLock        = false;

            try
            {
                // Lock the entry to ensure it will not be removed while the connectio attempt is occuring.
                while (!acquiredConnectionLock)
                {
                    entry = GetOrCreateEntry(endpoint, ref acquiredConnectionLock);

                    if (entry.Connections.Length >= this.connectionOptions.ConnectionsPerEndpoint)
                    {
                        result = entry.Connections;
                        break;
                    }

                    ThrowIfRecentFailure(endpoint, entry);

                    // Wait a short time before reattempting to acquire the lock
                    await Task.Delay(10);
                }

                // Attempt to connect.
                Connection connection = default;
                var        now        = DateTime.UtcNow;
                try
                {
                    connection = await this.ConnectAsync(endpoint);

                    entry  = OnConnectedInternal(endpoint, connection);
                    result = entry.Connections;
                }
                catch (Exception exception)
                {
                    OnConnectionFailed(endpoint, now);
                    throw new ConnectionFailedException(
                              $"Unable to connect to endpoint {endpoint}. See {nameof(exception.InnerException)}", exception);
                }
            }
            finally
            {
                if (acquiredConnectionLock)
                {
                    entry.ReleaseLock();
                }
            }

            nextConnection = (nextConnection + 1) % result.Length;
            return(result[nextConnection]);
        }
Exemple #2
0
        private void OnConnectionFailed(SiloAddress address, DateTime lastFailure)
        {
            bool            acquiredConnectionLock = false;
            ConnectionEntry entry = default;

            lock (this.collectionLock)
            {
                try
                {
                    entry = this.GetOrCreateEntry(address, ref acquiredConnectionLock);

                    if (entry.LastFailure.HasValue)
                    {
                        var ticks = Math.Max(lastFailure.Ticks, entry.LastFailure.Value.Ticks);
                        lastFailure = new DateTime(ticks);
                    }

                    // Clean up defunct connections
                    var connections = entry.Connections;
                    foreach (var c in connections)
                    {
                        if (!c.IsValid)
                        {
                            connections = connections.Remove(c);
                        }
                    }

                    this.connections[address] = entry.WithLastFailure(lastFailure).WithConnections(connections);
                }
                finally
                {
                    if (acquiredConnectionLock)
                    {
                        entry.ReleaseLock();
                    }
                }
            }
        }