1
1
import logging
2
+ import time
2
3
from typing import Dict , List , Optional
3
4
4
5
from confluent_kafka import OFFSET_BEGINNING
@@ -71,6 +72,10 @@ def __repr__(self):
71
72
def changelog_name (self ) -> str :
72
73
return self ._changelog_name
73
74
75
+ @property
76
+ def changelog_highwater (self ) -> int :
77
+ return self ._changelog_highwater
78
+
74
79
@property
75
80
def partition_num (self ) -> int :
76
81
return self ._partition_num
@@ -315,6 +320,7 @@ def __init__(self, consumer: BaseConsumer, topic_manager: TopicManager):
315
320
self ._consumer = consumer
316
321
self ._topic_manager = topic_manager
317
322
self ._recovery_partitions : Dict [int , Dict [str , RecoveryPartition ]] = {}
323
+ self ._last_progress_logged_time = time .monotonic ()
318
324
319
325
@property
320
326
def partitions (self ) -> Dict [int , Dict [str , RecoveryPartition ]]:
@@ -529,9 +535,7 @@ def revoke_partition(self, partition_num: int):
529
535
def _update_recovery_status (self ):
530
536
rp_revokes = []
531
537
for rp in dict_values (self ._recovery_partitions ):
532
- position = self ._consumer .position (
533
- [ConfluentPartition (rp .changelog_name , rp .partition_num )]
534
- )[0 ].offset
538
+ position = self ._get_changelog_offset (rp )
535
539
rp .set_recovery_consume_position (position )
536
540
if rp .finished_recovery_check :
537
541
rp_revokes .append (rp )
@@ -549,12 +553,33 @@ def _recovery_loop(self) -> None:
549
553
A RecoveryPartition is unassigned immediately once fully updated.
550
554
"""
551
555
while self .recovering :
556
+ self ._log_recovery_progress ()
552
557
if (msg := self ._consumer .poll (1 )) is None :
553
558
self ._update_recovery_status ()
554
559
else :
555
560
msg = raise_for_msg_error (msg )
556
561
rp = self ._recovery_partitions [msg .partition ()][msg .topic ()]
557
562
rp .recover_from_changelog_message (changelog_message = msg )
558
563
564
+ def _log_recovery_progress (self ) -> None :
565
+ """
566
+ Periodically log the recovery progress of all RecoveryPartitions.
567
+ """
568
+ if self ._last_progress_logged_time < time .monotonic () - 10 :
569
+ for rp in dict_values (self ._recovery_partitions ):
570
+ last_consumed_offset = self ._get_changelog_offset (rp ) - 1
571
+ logger .info (
572
+ f"Recovery progress for { rp } : { last_consumed_offset } / { rp .changelog_highwater } "
573
+ )
574
+ self ._last_progress_logged_time = time .monotonic ()
575
+
576
+ def _get_changelog_offset (self , rp : RecoveryPartition ) -> int :
577
+ """
578
+ Get the current offset of the changelog partition.
579
+ """
580
+ return self ._consumer .position (
581
+ [ConfluentPartition (rp .changelog_name , rp .partition_num )]
582
+ )[0 ].offset
583
+
559
584
def stop_recovery (self ):
560
585
self ._running = False
0 commit comments