Exemple #1
0
        /// <summary>
        /// Send kafka payload to server and receive a task event when response is received.
        /// </summary>
        /// <typeparam name="T">A Kafka response object return by decode function.</typeparam>
        /// <param name="request">The IKafkaRequest to send to the kafka servers.</param>
        /// <returns></returns>
        public Task <List <T> > SendAsync <T>(IKafkaRequest <T> request)
        {
            //assign unique correlationId
            request.CorrelationId = NextCorrelationId();

            var tcs         = new TaskCompletionSource <List <T> >();
            var asynRequest = new AsyncRequestItem(request.CorrelationId);

            asynRequest.ReceiveTask.Task.ContinueWith(data =>
            {
                try
                {
                    var response = request.Decode(data.Result);
                    tcs.SetResult(response.ToList());

                    //TODO should we check for errors type here and throw?
                }
                catch (Exception ex)
                {
                    tcs.SetException(ex);
                }
            });

            if (_requestIndex.TryAdd(request.CorrelationId, asynRequest) == false)
            {
                throw new ApplicationException("Failed to register request for async response.");
            }

            SendAsync(request.Encode());

            return(tcs.Task);
        }
Exemple #2
0
        /// <summary>
        /// Send kafka payload to server and receive a task event when response is received.
        /// </summary>
        /// <typeparam name="T">A Kafka response object return by decode function.</typeparam>
        /// <param name="request">The IKafkaRequest to send to the kafka servers.</param>
        /// <returns></returns>
        public async Task <List <T> > SendAsync <T>(IKafkaRequest <T> request)
        {
            //assign unique correlationId
            request.CorrelationId = NextCorrelationId();

            //if response is expected, register a receive data task and send request
            if (request.ExpectResponse)
            {
                var asyncRequest = new AsyncRequestItem(request.CorrelationId);

                try
                {
                    AddAsyncRequestItemToResponseQueue(asyncRequest);

                    await SendAsync(request.Encode()).ConfigureAwait(false);
                }
                catch (OperationCanceledException ex)
                {
                    TriggerMessageTimeout(asyncRequest);
                }

                var response = await asyncRequest.ReceiveTask.Task.ConfigureAwait(false);

                return(request.Decode(response).ToList());
            }


            //no response needed, just send
            await SendAsync(request.Encode()).ConfigureAwait(false);

            //TODO should this return a response of success for request?
            return(new List <T>());
        }
Exemple #3
0
        /// <summary>
        /// Send kafka payload to server and receive a task event when response is received.
        /// </summary>
        /// <typeparam name="T">A Kafka response object return by decode function.</typeparam>
        /// <param name="request">The IKafkaRequest to send to the kafka servers.</param>
        /// <returns></returns>
        public async Task <List <T> > SendAsync <T>(IKafkaRequest <T> request)
        {
            //assign unique correlationId
            request.CorrelationId = NextCorrelationId();

            //if response is expected, register a receive data task and send request
            if (request.ExpectResponse)
            {
                var asyncRequest = new AsyncRequestItem(request.CorrelationId);

                if (_requestIndex.TryAdd(request.CorrelationId, asyncRequest) == false)
                {
                    throw new ApplicationException("Failed to register request for async response.");
                }

                SendAsync(request.Encode());

                var response = await asyncRequest.ReceiveTask.Task.ConfigureAwait(false);

                return(request.Decode(response).ToList());
            }


            //no response needed, just send
            await SendAsync(request.Encode()).ConfigureAwait(false);

            //TODO should this return a response of success for request?
            return(new List <T>());
        }
Exemple #4
0
 private void AddAsyncRequestItemToResponseQueue(AsyncRequestItem requestItem)
 {
     if (requestItem == null)
     {
         return;
     }
     if (_requestsByCorrelation.TryAdd(requestItem.CorrelationId, requestItem) == false)
     {
         throw new KafkaException("Failed to register request for async response.");
     }
 }
Exemple #5
0
 private void AddAsyncRequestItemToResponseQueue(AsyncRequestItem requestItem)
 {
     if (requestItem == null)
     {
         return;
     }
     requestItem.CreatedOnUtc = DateTime.UtcNow;
     if (_requestIndex.TryAdd(requestItem.CorrelationId, requestItem) == false)
     {
         throw new ApplicationException("Failed to register request for async response.");
     }
 }
Exemple #6
0
        /// <summary>
        /// Send kafka payload to server and receive a task event when response is received.
        /// </summary>
        /// <typeparam name="T">A Kafka response object return by decode function.</typeparam>
        /// <param name="request">The IRequest to send to the kafka servers.</param>
        /// <param name="context">The context for the request.</param>
        /// <param name="token">Cancellation token used to cancel the transfer.</param>
        /// <returns></returns>
        public async Task <T> SendAsync <T>(IRequest <T> request, CancellationToken token, IRequestContext context = null) where T : class, IResponse
        {
            var version = context?.ApiVersion;

            if (!version.HasValue)
            {
                version = await GetVersionAsync(request.ApiKey, token).ConfigureAwait(false);
            }
            context = new RequestContext(NextCorrelationId(), version, context?.ClientId, context?.Encoders ?? _configuration.Encoders, context?.ProtocolType ?? request.ProtocolType, context?.OnProduceRequestMessages ?? _configuration.OnProduceRequestMessages);

            var payload = KafkaEncoder.Encode(context, request);

            _log.Info(() => LogEvent.Create($"Sending {request.ApiKey} with correlation id {context.CorrelationId} (v {version.GetValueOrDefault()}, {payload.Buffer.Length} bytes) to {Endpoint}"));
            _log.Debug(() => LogEvent.Create($"-----> {request.ApiKey} with correlation id {context.CorrelationId} to {Endpoint}\n{request.ToFormattedString()}"));
            if (!request.ExpectResponse)
            {
                await _socket.WriteAsync(payload, token).ConfigureAwait(false);

                return(default(T));
            }

            using (var asyncRequest = new AsyncRequestItem(context.CorrelationId, request.ApiKey, _configuration.RequestTimeout)) {
                try {
                    AddAsyncRequestItemToResponseQueue(asyncRequest);
                    ExceptionDispatchInfo exceptionDispatchInfo = null;

                    try {
                        await _socket.WriteAsync(payload, token).ConfigureAwait(false);
                    } catch (Exception ex) {
                        exceptionDispatchInfo = ExceptionDispatchInfo.Capture(ex);
                    }

                    asyncRequest.MarkRequestAsSent(exceptionDispatchInfo, TriggerMessageTimeout);
                } catch (OperationCanceledException) {
                    TriggerMessageTimeout(asyncRequest);
                }

                var response = await asyncRequest.ReceiveTask.Task.ThrowIfCancellationRequested(token).ConfigureAwait(false);

                _log.Info(() => LogEvent.Create($"Receiving {request.ApiKey} with correlation id {context.CorrelationId} (v {version.GetValueOrDefault()}, {response.Length} bytes) from {Endpoint}"));
                var result = KafkaEncoder.Decode <T>(context, response);
                _log.Debug(() => LogEvent.Create($"<------- {request.ApiKey} with correlation id {context.CorrelationId} from {Endpoint}\n{result.ToFormattedString()}"));
                return(result);
            }
        }
        /// <summary>
        /// Send kafka payload to server and receive a task event when response is received.
        /// </summary>
        /// <typeparam name="T">A Kafka response object return by decode function.</typeparam>
        /// <param name="request">The IKafkaRequest to send to the kafka servers.</param>
        /// <returns></returns>
        public async Task <List <T> > SendAsync <T>(IKafkaRequest <T> request)
        {
            //assign unique correlationId
            request.CorrelationId = NextCorrelationId();

            var asyncRequest = new AsyncRequestItem(request.CorrelationId);

            if (_requestIndex.TryAdd(request.CorrelationId, asyncRequest) == false)
            {
                throw new ApplicationException("Failed to register request for async response.");
            }

            await SendAsync(request.Encode());

            var response = await asyncRequest.ReceiveTask.Task;

            return(request.Decode(response).ToList());
        }
        /// <summary>
        /// Send kafka payload to server and receive a task event when response is received.
        /// </summary>
        /// <typeparam name="T">A Kafka response object return by decode function.</typeparam>
        /// <param name="request">The IKafkaRequest to send to the kafka servers.</param>
        /// <returns></returns>

        public async Task <List <T> > SendAsync <T>(IKafkaRequest <T> request)
        {
            //assign unique correlationId
            request.CorrelationId = NextCorrelationId();

            _log.DebugFormat("Entered SendAsync for CorrelationId:{0} Connection:{1} ", request.CorrelationId, Endpoint);
            //if response is expected, register a receive data task and send request
            if (request.ExpectResponse)
            {
                using (var asyncRequest = new AsyncRequestItem(request.CorrelationId))
                {
                    try
                    {
                        AddAsyncRequestItemToResponseQueue(asyncRequest);
                        ExceptionDispatchInfo exceptionDispatchInfo = null;

                        try
                        {
                            await _client.WriteAsync(request.Encode()).ConfigureAwait(false);
                        }
                        catch (Exception ex)
                        {
                            exceptionDispatchInfo = ExceptionDispatchInfo.Capture(ex);
                        }

                        asyncRequest.MarkRequestAsSent(exceptionDispatchInfo, _responseTimeoutMs, TriggerMessageTimeout);
                    }
                    catch (OperationCanceledException)
                    {
                        TriggerMessageTimeout(asyncRequest);
                    }

                    var response = await asyncRequest.ReceiveTask.Task.ConfigureAwait(false);

                    return(request.Decode(response).ToList());
                }
            }

            //no response needed, just send
            await _client.WriteAsync(request.Encode()).ConfigureAwait(false);

            //TODO should this return a response of success for request?
            return(new List <T>());
        }
Exemple #9
0
        private void TriggerMessageTimeout(AsyncRequestItem asyncRequestItem)
        {
            if (asyncRequestItem == null)
            {
                return;
            }

            AsyncRequestItem request;

            _requestsByCorrelation.TryRemove(asyncRequestItem.CorrelationId, out request);

            if (_disposeToken.IsCancellationRequested)
            {
                asyncRequestItem.ReceiveTask.TrySetException(new ObjectDisposedException("The object is being disposed and the connection is closing."));
            }
            else
            {
                asyncRequestItem.ReceiveTask.TrySetException(new TimeoutException($"Timeout expired after {asyncRequestItem.Timeout.TotalMilliseconds} ms."));
            }
        }
Exemple #10
0
        private void TriggerMessageTimeout(AsyncRequestItem asyncRequestItem)
        {
            if (asyncRequestItem == null)
            {
                return;
            }

            AsyncRequestItem request;

            _requestIndex.TryRemove(asyncRequestItem.CorrelationId, out request); //just remove it from the index

            if (_disposeToken.IsCancellationRequested)
            {
                asyncRequestItem.ReceiveTask.TrySetException(
                    new ObjectDisposedException("The object is being disposed and the connection is closing."));
            }
            else
            {
                asyncRequestItem.ReceiveTask.TrySetException(new ResponseTimeoutException(
                                                                 string.Format("Timeout Expired. Client failed to receive a response from server after waiting {0}ms.",
                                                                               _responseTimeoutMS)));
            }
        }
        /// <summary>
        /// Send kafka payload to server and receive a task event when response is received.
        /// </summary>
        /// <typeparam name="T">A Kafka response object return by decode function.</typeparam>
        /// <param name="request">The IKafkaRequest to send to the kafka servers.</param>
        /// <returns></returns>
        public async Task <List <T> > SendAsync <T>(IKafkaRequest <T> request)
        {
            //assign unique correlationId
            request.Correlation = NextCorrelationId();

            var asyncRequest = new AsyncRequestItem(request.Correlation);

            if (_requestIndex.TryAdd(request.Correlation, asyncRequest) == false)
            {
                throw new ApplicationException("Failed to register request for async response.");
            }

            // Encode the request into a stream
            var stream = new BinaryStream();

            request.Encode(stream);

            // Write to the socket
            await _client.WriteAsync(stream);

            var response = await asyncRequest.ReceiveTask.Task;

            return(request.Decode(response).ToList());
        }
        private void TriggerMessageTimeout(AsyncRequestItem asyncRequestItem)
        {
            if (asyncRequestItem == null)
            {
                return;
            }

            AsyncRequestItem request;

            //just remove it from the index
            _requestIndex.TryRemove(asyncRequestItem.CorrelationId, out request);

            if (_disposeToken.IsCancellationRequested)
            {
                asyncRequestItem.ReceiveTask.TrySetException(
                    new ObjectDisposedException("The object is being disposed and the connection is closing."));
            }
            else
            {
                asyncRequestItem.ReceiveTask.TrySetException(new ResponseTimeoutException(
                                                                 string.Format("Timeout reached for endpoint {0} (after waiting {1})",
                                                                               _client.Endpoint, _responseTimeoutMs)));
            }
        }