public async Task <MessageRelayConnection> SelectNextConnectionAsync() { IReadOnlyList <MessageRelayRecord> allRecords = await this.messageRelayRecords.GetAllMessageRelayRecordsAsync(); if (allRecords.Count == 0) { this.logger.LogWarning("No relay addresses in the store - can't select a connection candidate!"); return(null); } // peers, shortest success ago first var hottestRecords = allRecords .Where(x => !IsExcluded(x)) // e.g. if we are already connected, or the last error is less than a certain time ago .OrderBy(x => DateTimeOffset.UtcNow - x.LastSeenUtc) // then, try the best candidates first .ThenByDescending(x => DateTimeOffset.UtcNow - x.LastErrorUtc) // then, try the candidates where the last error is longest ago .ToList(); if (hottestRecords.Count == 0) { this.logger.LogDebug("After applying the filtering rules, no connection candidates remain for selection."); return(null); } MessageRelayRecord messageRelayRecord = hottestRecords[0]; this.logger.LogDebug($"Selected connection candidate {messageRelayRecord}, last seen {DateTimeOffset.UtcNow - messageRelayRecord.LastSeenUtc} ago, last error {DateTimeOffset.UtcNow - messageRelayRecord.LastErrorUtc} ago."); var messageRelayConnection = new MessageRelayConnection(messageRelayRecord, this.cancellation.Token); bool addSuccess = this.connections.TryAdd(messageRelayRecord.Id, messageRelayConnection); Debug.Assert(addSuccess, $"Bug: Peer {messageRelayRecord} was already in the ConnectedPeers dictionary - that should not happen."); return(messageRelayConnection); }
public MessageRelayConnection(MessageRelayRecord messageMessageRelayRecord, CancellationToken cancellationToken) { this.MessageRelayRecord = messageMessageRelayRecord; this.TcpClient = new TcpClient(AddressFamily.InterNetworkV6); this.TcpClient.Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false); this.cancellationToken = cancellationToken; }
bool IsExcluded(MessageRelayRecord relay) { if (this.connections.ContainsKey(relay.Id)) { this.logger.LogDebug($"Peer {relay} is excluded, because it's in the list of connected peers."); return(true); } if (relay.LastErrorUtc != default) { var timeSinceLastError = DateTimeOffset.UtcNow - relay.LastErrorUtc; if (timeSinceLastError <= TimeSpan.FromSeconds(60)) { this.logger.LogDebug( $"Peer (MessageRelay) {relay} is excluded, because it's last error is only {timeSinceLastError} ago."); return(true); } } return(false); }