package cn.reghao.tnb.search.esapp.log.mq;

import cn.reghao.jutil.jdk.serializer.JsonConverter;
import cn.reghao.jutil.jdk.thread.ThreadPoolWrapper;
import cn.reghao.jutil.jdk.web.log.NginxLog;
import cn.reghao.tnb.search.esapp.config.AppProperties;
import cn.reghao.tnb.search.esapp.log.service.NginxLogService;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.CommitFailedException;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;

/**
 * @author reghao
 * @date 2022-04-02 11:20:44
 */
@Slf4j
@Component
public class KafkaSub {
    private final ExecutorService threadPool = ThreadPoolWrapper.threadPool("kafka-consumer");
    private final String topic;
    private final KafkaConsumer<String,String> consumer;
    private final NginxLogService nginxLogService;

    public KafkaSub(AppProperties appProperties, NginxLogService nginxLogService) {
        this.topic = appProperties.getKafkaTopic();
        this.nginxLogService = nginxLogService;

        Properties properties = new Properties();
        properties.put("bootstrap.servers", appProperties.getKafkaUri());
        // 消费者群组
        properties.put("group.id", "test");
        // 自动提交偏移量
        properties.put("enable.auto.commit", "true");
        // 自动提交偏移量的频率, 这里设置为 5s
        properties.put("auto.commit.interval.ms", "5000");
        properties.put("session.timeout.ms", "30000");
        properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        this.consumer = new KafkaConsumer<>(properties);
    }

    @PostConstruct
    public void consume() {
        consumer.subscribe(Collections.singletonList(topic));
        threadPool.submit(new ConsumeTask());
    }

    class ConsumeTask implements Runnable {
        public void run() {
            try {
                while (!Thread.interrupted()) {
                    List<NginxLog> list = new ArrayList<>();
                    ConsumerRecords<String, String> records = consumer.poll(Duration.ofSeconds(100));
                    for (ConsumerRecord<String, String> record : records) {
                        String key = record.key();
                        String value = record.value();
                        NginxLog nginxLog = JsonConverter.jsonToObject(value, NginxLog.class);
                        list.add(nginxLog);
                    }
                    nginxLogService.processNginxLogs(list);
                    consumer.commitAsync();
                }
            } catch (CommitFailedException e) {
                log.error("commit failed", e);
            } finally {
                consumer.close();
            }
        }
    }
}
