public IEnumerable <T> Stream(CancellationToken cancellationToken)
        {
            var kafkaConsumerBuilder = CreateKafkaConsumerBuilder();

            using (var kafkaConsumer = kafkaConsumerBuilder.Build())
            {
                this.kafkaConsumer = kafkaConsumer;
                kafkaConsumer.Subscribe(topic);

                while (!cancellationToken.IsCancellationRequested)
                {
                    ConsumeResult <K, T> consumedResult;
                    try
                    {
                        consumedResult = kafkaConsumer.Consume(cancellationToken);

                        if (consumedResult?.IsPartitionEOF == true)
                        {
                            OnEOF?.Invoke();
                        }
                    }
                    catch (ConsumeException ex)
                    {
                        OnError?.Invoke(new StreamingError {
                            Reason = ex.Message, IsFatal = false
                        });
                        consumedResult = null;
                    }
                    catch (OperationCanceledException) {
                        consumedResult = null;
                    }

                    if (consumedResult?.Message != null)
                    {
                        yield return(consumedResult.Message.Value);
                    }
                }

                // Gracefully close the consumer, liberating the group offsets, etc.
                kafkaConsumer.Close();
            }
        }
        /// <summary>
        /// Retrieves the stream of messages from the change tracking source.
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns>IEnumerable of messages of type Change</returns>
        public IEnumerable <Change> Stream(CancellationToken cancellationToken)
        {
            Stopwatch            processTime = Stopwatch.StartNew();
            IEnumerable <Change> changes     = null;
            TimeSpan             delay       = TimeSpan.FromSeconds(0);
            bool alreadyInvokeEOF            = false;

            try
            {
                if (CommitEnable)
                {
                    ContextHandler.InitContext();
                }
                else
                {
                    ContextHandler.InitContext(InitialChangeTable == null ? 0 : (long)InitialChangeTable);
                }
            }
            catch (Exception ex)
            {
                OnError?.Invoke(new StreamingError {
                    IsFatal = true, Reason = ex.Message
                });
            }

            while (!cancellationToken.IsCancellationRequested)
            {
                using (var conn = Repository.CreateConnection())
                {
                    try
                    {
                        changes = null;

                        ContextHandler.UpdateDatabaseOffset(Repository.GetDatabaseOffset(conn));
                        if (ContextHandler.HasChanges())
                        {
                            changes          = GetChanges(conn, ContextHandler);
                            alreadyInvokeEOF = false;
                        }
                        else if (ContextHandler.isEOF() && !alreadyInvokeEOF)
                        {
                            OnEOF?.Invoke();
                            alreadyInvokeEOF = true;
                        }
                    }
                    catch (Exception cte)
                    {
                        OnError?.Invoke(new StreamingError {
                            IsFatal = cte is ChangeTrackingException, Reason = cte.Message
                        });
                        ContextHandler.RegisterError();

                        delay = delay.Add(TimeSpan.FromSeconds(5));
                        if (delay > TimeSpan.FromSeconds(15))
                        {
                            delay = TimeSpan.FromSeconds(15);
                        }
                    }

                    if (null != changes)
                    {
                        bool mustSync = false;
                        foreach (var change in changes)
                        {
                            if (change.ChangeOperation.Equals(ChangeOperationEnum.SYNC))
                            {
                                mustSync = true;
                            }
                            else
                            {
                                yield return(change);
                            }
                        }

                        delay = TimeSpan.FromSeconds(0);

                        ContextHandler.UpdateApplicationOffset();
                        if (mustSync && CommitEnable)
                        {
                            Commit();
                        }
                    }
                }

                processTime.Stop();

                var sleep = (delay + PollingInterval) - processTime.Elapsed;
                if (sleep.TotalMilliseconds > 0)
                {
                    Thread.Sleep(sleep);
                }

                processTime.Restart();
            }

            ContextHandler.Dispose();
        }