private async Task <TcpClient> ReEstablishConnectionAsync() { var attempts = 1; var reconnectionDelay = DefaultReconnectionTimeout; _log.WarnFormat("No connection to:{0}. Attempting to re-connect...", _endpoint); //clean up existing client using (_client) { _client = null; } while (_disposeToken.IsCancellationRequested == false) { try { if (OnReconnectionAttempt != null) { OnReconnectionAttempt(attempts++); } _client = new TcpClient(); await _client.ConnectAsync(_endpoint.Endpoint.Address, _endpoint.Endpoint.Port); _log.WarnFormat("Connection established to:{0}.", _endpoint); return(_client); } catch { reconnectionDelay = reconnectionDelay * DefaultReconnectionTimeoutMultiplier; _log.WarnFormat("Failed re-connection to:{0}. Will retry in:{1}", _endpoint, reconnectionDelay); } await Task.Delay(TimeSpan.FromMilliseconds(reconnectionDelay), _disposeToken.Token); } return(_client); }
private void SetDisposeExceptonToPenndingTasks(Exception exception = null) { var disposeException = new ObjectDisposedException("Object is disposing."); if (exception == null) { _log.WarnFormat("KafkaTcpSocket thread shutting down because of a dispose call."); _sendTaskQueue.DrainAndApply(t => t.Tcp.TrySetException(disposeException)); _readTaskQueue.DrainAndApply(t => t.Tcp.TrySetException(disposeException)); } else { _log.WarnFormat("KafkaTcpSocket not able to connect cancel all PenndingTasks."); _sendTaskQueue.DrainAndApply(t => t.Tcp.TrySetException(exception)); _readTaskQueue.DrainAndApply(t => t.Tcp.TrySetException(exception)); } }
private void DedicatedSocketTask() { while (_disposeToken.IsCancellationRequested == false) { try { _processNetworkstreamTasksAction(); } catch (Exception ex) { if (_disposeToken.IsCancellationRequested) { _log.WarnFormat("KafkaTcpSocket thread shutting down because of a dispose call."); var disposeException = new ObjectDisposedException("Object is disposing."); _sendTaskQueue.DrainAndApply(t => t.Tcp.TrySetException(disposeException)); _readTaskQueue.DrainAndApply(t => t.Tcp.TrySetException(disposeException)); return; } if (ex is ServerDisconnectedException) { if (OnServerDisconnected != null) { OnServerDisconnected(); } _log.ErrorFormat(ex.Message); continue; } _log.ErrorFormat("Exception occured in Socket handler task. Exception: {0}", ex); } } }
/// <summary> /// Given a collection of server connections, query for the topic metadata. /// </summary> /// <param name="connections">The server connections to query. Will cycle through the collection, starting at zero until a response is received.</param> /// <param name="topics">The collection of topics to get metadata for.</param> /// <returns>MetadataResponse validated to be complete.</returns> public async Task <MetadataResponse> Get(IKafkaConnection[] connections, IEnumerable <string> topics) { var request = new MetadataRequest { Topics = topics.ToList() }; if (request.Topics.Count <= 0) { return(null); } var maxRetryAttempt = 2; var performRetry = false; var retryAttempt = 0; MetadataResponse metadataResponse = null; do { performRetry = false; metadataResponse = await GetMetadataResponse(connections, request); if (metadataResponse == null) { return(null); } foreach (var validation in ValidateResponse(metadataResponse)) { switch (validation.Status) { case ValidationResult.Retry: performRetry = true; _log.WarnFormat(validation.Message); break; case ValidationResult.Error: throw validation.Exception; } } await BackoffOnRetry(++retryAttempt, performRetry).ConfigureAwait(false); } while (retryAttempt < maxRetryAttempt && _interrupted == false && performRetry); return(metadataResponse); }
public async Task ShouldRetryWhenReceiveAnRetryErrorCode(ErrorResponseCode errorCode) { var conn = Substitute.For <IKafkaConnection>(); conn.SendAsync(Arg.Any <IKafkaRequest <MetadataResponse> >()) .Returns(x => CreateMetadataResponse(errorCode), x => CreateMetadataResponse(errorCode)); using (var provider = new KafkaMetadataProvider(_log)) { var response = await provider.Get(new[] { conn }, new[] { "Test" }); } Received.InOrder(() => { conn.SendAsync(Arg.Any <IKafkaRequest <MetadataResponse> >()); _log.WarnFormat("Backing off metadata request retry. Waiting for {0}ms.", 100); conn.SendAsync(Arg.Any <IKafkaRequest <MetadataResponse> >()); }); }
/// <summary> /// (Re-)establish the Kafka server connection. /// Assumes that the caller has already obtained the <c>_clientLock</c> /// </summary> private async Task <TcpClient> ReEstablishConnectionAsync() { var attempts = 1; var reconnectionDelay = DefaultReconnectionTimeout; _log.DebugFormat("No connection to:{0}. Attempting to connect...", _endpoint); _client = null; while (_disposeToken.IsCancellationRequested == false && _maxRetry > attempts) { attempts++; try { if (OnReconnectionAttempt != null) { OnReconnectionAttempt(attempts); } _client = new TcpClient(); var connectTask = _client.ConnectAsync(_endpoint.Endpoint.Address, _endpoint.Endpoint.Port); await Task.WhenAny(connectTask, _disposeTask).ConfigureAwait(false); if (_disposeToken.IsCancellationRequested) { throw new ObjectDisposedException(string.Format("Object is disposing (KafkaTcpSocket for endpoint: {0})", Endpoint)); } await connectTask; if (!_client.Connected) { throw new BrokerConnectionException(string.Format("Lost connection to server: {0}", _endpoint), _endpoint); } _log.DebugFormat("Connection established to:{0}.", _endpoint); return(_client); } catch (Exception ex) { reconnectionDelay = reconnectionDelay * DefaultReconnectionTimeoutMultiplier; reconnectionDelay = Math.Min(reconnectionDelay, (int)_maximumReconnectionTimeout.TotalMilliseconds); _log.WarnFormat("Failed connection to:{0}. Will retry in:{1} Exception{2}", _endpoint, reconnectionDelay, ex.Message); if (_maxRetry < attempts) { throw; } } await Task.Delay(TimeSpan.FromMilliseconds(reconnectionDelay), _disposeToken.Token).ConfigureAwait(false); } return(_client); }
public static void DisposeSafely(this object objToDispose, IKafkaLog log) { var disposable = objToDispose as IDisposable; if (disposable != null) { var className = disposable.GetType().Name; try { disposable.Dispose(); log?.DebugFormat("Successfully disposed {0}", className); } catch (Exception e) { log?.WarnFormat("Error disposing {0}, Exception {1}", className, e); } } }