예제 #1
0
 public KafkaConsumerStream(IKafkaMessageStream <Client.Messages.Message> stream)
 {
     _tokenSource = new CancellationTokenSource();
     _stream      = stream.GetCancellable(_tokenSource.Token);
     _thread      = new Thread(RunConsumer);
 }
예제 #2
0
        private Task StartConsumer(
            IKafkaMessageStream <Client.Messages.Message> stream,
            Action <IEnumerable <ConsumedMessage> > dataSubscriber,
            Action <Exception> errorSubscriber)
        {
            var completionSource = new TaskCompletionSource <bool>();
            var thread           = new Thread(() =>
            {
                Logger.Info($"Starting consumer thread {Thread.CurrentThread.ManagedThreadId}");
                while (_consumer != null)
                {
                    var tokenSource = new CancellationTokenSource(_batchTimeoutMs);
                    try
                    {
                        var cancellable = stream.GetCancellable(tokenSource.Token);
                        var messages    = cancellable
                                          .Select(message => message.AsConsumedMessage())
                                          .ToArray();

                        Logger.Debug($"Received {messages.Length} messages.");
                        if (messages.Length == 0)
                        {
                            continue;
                        }

                        for (var i = 0; i < messages.Length; i += _maxBatchSize)
                        {
                            if (_consumer == null)
                            {
                                break;
                            }

                            var taken = messages.Skip(i).Take(_maxBatchSize).ToArray();
                            Logger.Debug($"Skip {i}, take {_maxBatchSize}, get {taken.Length}.");

                            dataSubscriber(taken);

                            var map = taken
                                      .GroupBy(m => m.Partition)
                                      .ToDictionary(kvp => kvp.Key, kvp => kvp.Max(m => m.Offset + 1));

                            foreach (var kvp in map)
                            {
                                Commit(kvp.Key, kvp.Value);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Error($"Exception in consumer {_group} for {_topic}. Restarting...", ex);
                        errorSubscriber?.Invoke(ex);

                        Restart();
                        break;
                    }
                    finally
                    {
                        tokenSource.Dispose();
                    }
                }
                Logger.Info($"Ending consumer thread {Thread.CurrentThread.ManagedThreadId}");
                completionSource.SetResult(true);
            });

            _threadList.Add(thread);
            thread.Start();

            return(completionSource.Task);
        }