@ -36,12 +36,14 @@ import org.thingsboard.server.queue.common.consumer.QueueConsumerManager;
import org.thingsboard.server.queue.common.state.KafkaQueueStateService ;
import org.thingsboard.server.queue.common.state.KafkaQueueStateService ;
import org.thingsboard.server.queue.common.state.QueueStateService ;
import org.thingsboard.server.queue.common.state.QueueStateService ;
import org.thingsboard.server.queue.discovery.QueueKey ;
import org.thingsboard.server.queue.discovery.QueueKey ;
import org.thingsboard.server.queue.discovery.TopicService ;
import org.thingsboard.server.queue.edqs.EdqsConfig ;
import org.thingsboard.server.queue.edqs.EdqsConfig ;
import org.thingsboard.server.queue.edqs.EdqsQueue ;
import org.thingsboard.server.queue.edqs.EdqsQueueFactory ;
import org.thingsboard.server.queue.edqs.KafkaEdqsComponent ;
import org.thingsboard.server.queue.edqs.KafkaEdqsComponent ;
import org.thingsboard.server.queue.edqs.KafkaEdqsQueueFactory ;
import org.thingsboard.server.queue.kafka.TbKafkaAdmin ;
import org.thingsboard.server.queue.kafka.TbKafkaConsumerTemplate ;
import java.util.HashMap ;
import java.util.Map ;
import java.util.Set ;
import java.util.Set ;
import java.util.UUID ;
import java.util.UUID ;
import java.util.concurrent.atomic.AtomicInteger ;
import java.util.concurrent.atomic.AtomicInteger ;
@ -56,8 +58,7 @@ public class KafkaEdqsStateService implements EdqsStateService {
private final EdqsConfig config ;
private final EdqsConfig config ;
private final EdqsPartitionService partitionService ;
private final EdqsPartitionService partitionService ;
private final EdqsQueueFactory queueFactory ;
private final KafkaEdqsQueueFactory queueFactory ;
private final TopicService topicService ;
@Autowired @Lazy
@Autowired @Lazy
private EdqsProcessor edqsProcessor ;
private EdqsProcessor edqsProcessor ;
@ -73,15 +74,16 @@ public class KafkaEdqsStateService implements EdqsStateService {
@Override
@Override
public void init ( PartitionedQueueConsumerManager < TbProtoQueueMsg < ToEdqsMsg > > eventConsumer ) {
public void init ( PartitionedQueueConsumerManager < TbProtoQueueMsg < ToEdqsMsg > > eventConsumer ) {
TbKafkaAdmin queueAdmin = queueFactory . getEdqsQueueAdmin ( ) ;
stateConsumer = PartitionedQueueConsumerManager . < TbProtoQueueMsg < ToEdqsMsg > > create ( )
stateConsumer = PartitionedQueueConsumerManager . < TbProtoQueueMsg < ToEdqsMsg > > create ( )
. queueKey ( new QueueKey ( ServiceType . EDQS , EdqsQueue . STATE . getTopic ( ) ) )
. queueKey ( new QueueKey ( ServiceType . EDQS , config . getState Topic ( ) ) )
. topic ( EdqsQueue . STATE . getTopic ( ) )
. topic ( config . getState Topic ( ) )
. pollInterval ( config . getPollInterval ( ) )
. pollInterval ( config . getPollInterval ( ) )
. msgPackProcessor ( ( msgs , consumer , config ) - > {
. msgPackProcessor ( ( msgs , consumer , config ) - > {
for ( TbProtoQueueMsg < ToEdqsMsg > queueMsg : msgs ) {
for ( TbProtoQueueMsg < ToEdqsMsg > queueMsg : msgs ) {
try {
try {
ToEdqsMsg msg = queueMsg . getValue ( ) ;
ToEdqsMsg msg = queueMsg . getValue ( ) ;
edqsProcessor . process ( msg , EdqsQueue . STATE ) ;
edqsProcessor . process ( msg , false ) ;
if ( stateReadCount . incrementAndGet ( ) % 100000 = = 0 ) {
if ( stateReadCount . incrementAndGet ( ) % 100000 = = 0 ) {
log . info ( "[state] Processed {} msgs" , stateReadCount . get ( ) ) ;
log . info ( "[state] Processed {} msgs" , stateReadCount . get ( ) ) ;
}
}
@ -91,15 +93,15 @@ public class KafkaEdqsStateService implements EdqsStateService {
}
}
consumer . commit ( ) ;
consumer . commit ( ) ;
} )
} )
. consumerCreator ( ( config , partitionId ) - > queueFactory . createEdqsMsgConsumer ( EdqsQueue . STATE ) )
. consumerCreator ( ( config , partitionId ) - > queueFactory . createEdqsStateConsumer ( ) )
. queueAdmin ( queueFactory . getEdqsQueue Admin ( ) )
. queueAdmin ( queueAdmin )
. consumerExecutor ( eventConsumer . getConsumerExecutor ( ) )
. consumerExecutor ( eventConsumer . getConsumerExecutor ( ) )
. taskExecutor ( eventConsumer . getTaskExecutor ( ) )
. taskExecutor ( eventConsumer . getTaskExecutor ( ) )
. scheduler ( eventConsumer . getScheduler ( ) )
. scheduler ( eventConsumer . getScheduler ( ) )
. uncaughtErrorHandler ( edqsProcessor . getErrorHandler ( ) )
. uncaughtErrorHandler ( edqsProcessor . getErrorHandler ( ) )
. build ( ) ;
. build ( ) ;
queueStateService = new KafkaQueueStateService < > ( eventConsumer , stateConsumer ) ;
TbKafkaConsumerTemplate < TbProtoQueueMsg < ToEdqsMsg > > eventsToBackupKafkaConsumer = queueFactory . createEdqsEventsToBackupConsumer ( ) ;
eventsToBackupConsumer = QueueConsumerManager . < TbProtoQueueMsg < ToEdqsMsg > > builder ( )
eventsToBackupConsumer = QueueConsumerManager . < TbProtoQueueMsg < ToEdqsMsg > > builder ( )
. name ( "edqs-events-to-backup-consumer" )
. name ( "edqs-events-to-backup-consumer" )
. pollInterval ( config . getPollInterval ( ) )
. pollInterval ( config . getPollInterval ( ) )
@ -137,15 +139,35 @@ public class KafkaEdqsStateService implements EdqsStateService {
}
}
consumer . commit ( ) ;
consumer . commit ( ) ;
} )
} )
. consumerCreator ( ( ) - > queueFactory . createEdqsMsgConsumer ( EdqsQueue . EVENTS , "events-to-backup-consumer-group" ) ) // shared by all instances consumer group
. consumerCreator ( ( ) - > eventsToBackupKafkaConsumer )
. consumerExecutor ( eventConsumer . getConsumerExecutor ( ) )
. consumerExecutor ( eventConsumer . getConsumerExecutor ( ) )
. threadPrefix ( "edqs-events-to-backup" )
. threadPrefix ( "edqs-events-to-backup" )
. build ( ) ;
. build ( ) ;
stateProducer = EdqsProducer . builder ( )
stateProducer = EdqsProducer . builder ( )
. producer ( queueFactory . createEdqsMsgProducer ( EdqsQueue . STATE ) )
. producer ( queueFactory . createEdqsStateProducer ( ) )
. partitionService ( partitionService )
. partitionService ( partitionService )
. build ( ) ;
. build ( ) ;
queueStateService = KafkaQueueStateService . < TbProtoQueueMsg < ToEdqsMsg > , TbProtoQueueMsg < ToEdqsMsg > > builder ( )
. eventConsumer ( eventConsumer )
. stateConsumer ( stateConsumer )
. eventsStartOffsetsProvider ( ( ) - > {
// taking start offsets for events topics from the events-to-backup consumer group,
// since eventConsumer doesn't use consumer group management and thus offset tracking
// (because we need to be able to consume the same topic-partition by multiple instances)
Map < String , Long > offsets = new HashMap < > ( ) ;
try {
queueAdmin . getConsumerGroupOffsets ( eventsToBackupKafkaConsumer . getGroupId ( ) )
. forEach ( ( topicPartition , offsetAndMetadata ) - > {
offsets . put ( topicPartition . topic ( ) , offsetAndMetadata . offset ( ) ) ;
} ) ;
} catch ( Exception e ) {
log . error ( "Failed to get consumer group offsets for {}" , eventsToBackupKafkaConsumer . getGroupId ( ) , e ) ;
}
return offsets ;
} )
. build ( ) ;
}
}
@Override
@Override
@ -153,7 +175,7 @@ public class KafkaEdqsStateService implements EdqsStateService {
if ( queueStateService . getPartitions ( ) . isEmpty ( ) ) {
if ( queueStateService . getPartitions ( ) . isEmpty ( ) ) {
Set < TopicPartitionInfo > allPartitions = IntStream . range ( 0 , config . getPartitions ( ) )
Set < TopicPartitionInfo > allPartitions = IntStream . range ( 0 , config . getPartitions ( ) )
. mapToObj ( partition - > TopicPartitionInfo . builder ( )
. mapToObj ( partition - > TopicPartitionInfo . builder ( )
. topic ( EdqsQueue . EVENTS . getTopic ( ) )
. topic ( config . getEvents Topic ( ) )
. partition ( partition )
. partition ( partition )
. build ( ) )
. build ( ) )
. collect ( Collectors . toSet ( ) ) ;
. collect ( Collectors . toSet ( ) ) ;