@@ -47,10 +47,14 @@ import (
4747)
4848
4949// KafkaSourceConnector implements SourceConnector for Kafka
50+ // defaultKafkaSourceProgressHeartbeat is how often an active consumer group session updates liveness while idle.
51+ const defaultKafkaSourceProgressHeartbeat = 60 * time .Second
52+
5053type KafkaSourceConnector struct {
5154 baseConnector
5255 connectorLogger
5356 connectorMetadata
57+ progressRecorder
5458 config * v1.KafkaSourceSpec
5559 consumer sarama.ConsumerGroup
5660 channelBufferSize int
@@ -65,6 +69,8 @@ type KafkaSourceConnector struct {
6569 testConsumeFunc func (ctx context.Context , topics []string , handler sarama.ConsumerGroupHandler ) error
6670 // readErrCh receives fatal errors from the consumer after Read returns; set during Read.
6771 readErrCh chan error
72+ // progressHeartbeatInterval overrides defaultKafkaSourceProgressHeartbeat when > 0 (tests only).
73+ progressHeartbeatInterval time.Duration
6874}
6975
7076// schemaCache caches Avro schemas by ID
@@ -792,6 +798,13 @@ type kafkaConsumerGroupHandler struct {
792798 readyOnce sync.Once // Protects ready channel from being closed multiple times
793799}
794800
801+ func (k * KafkaSourceConnector ) kafkaProgressHeartbeatInterval () time.Duration {
802+ if k .progressHeartbeatInterval > 0 {
803+ return k .progressHeartbeatInterval
804+ }
805+ return defaultKafkaSourceProgressHeartbeat
806+ }
807+
795808func (h * kafkaConsumerGroupHandler ) Setup (sarama.ConsumerGroupSession ) error {
796809 // Use sync.Once to ensure channel is closed only once
797810 // This protects against multiple Setup calls during rebalancing
@@ -811,6 +824,7 @@ func (h *kafkaConsumerGroupHandler) Setup(sarama.ConsumerGroupSession) error {
811824 }()
812825 close (h .ready )
813826 })
827+ h .connector .notifyProgress ()
814828 return nil
815829}
816830
@@ -823,6 +837,9 @@ func (h *kafkaConsumerGroupHandler) Cleanup(sarama.ConsumerGroupSession) error {
823837const kafkaMarkChannelBuffer = 256
824838
825839func (h * kafkaConsumerGroupHandler ) ConsumeClaim (session sarama.ConsumerGroupSession , claim sarama.ConsumerGroupClaim ) error {
840+ heartbeat := time .NewTicker (h .connector .kafkaProgressHeartbeatInterval ())
841+ defer heartbeat .Stop ()
842+
826843 markChan := make (chan * sarama.ConsumerMessage , kafkaMarkChannelBuffer )
827844
828845 markPending := func (message * sarama.ConsumerMessage ) {
@@ -845,6 +862,8 @@ func (h *kafkaConsumerGroupHandler) ConsumeClaim(session sarama.ConsumerGroupSes
845862
846863 for {
847864 select {
865+ case <- heartbeat .C :
866+ h .connector .notifyProgress ()
848867 case message := <- claim .Messages ():
849868 if message == nil {
850869 drainMarks ()
@@ -907,6 +926,7 @@ type KafkaSinkConnector struct {
907926 baseConnector
908927 connectorLogger
909928 connectorMetadata
929+ progressRecorder
910930 config * v1.KafkaSinkSpec
911931 producer sarama.SyncProducer
912932}
@@ -1059,6 +1079,7 @@ func (k *KafkaSinkConnector) Write(ctx context.Context, messages <-chan *types.M
10591079 if msg .Ack != nil {
10601080 msg .Ack ()
10611081 }
1082+ k .notifyProgress ()
10621083 }
10631084 }
10641085}
0 commit comments