From 9e7c084712816060c4b915048f4434a471ce7412 Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Wed, 15 Jul 2026 07:59:15 +0300 Subject: [PATCH] Deduplicate Kafka signal processors --- .../KafkaSignalProcessorSupport.java | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/main/java/ru/nbch/credit_tracker/service/mode/monitoring/KafkaSignalProcessorSupport.java diff --git a/src/main/java/ru/nbch/credit_tracker/service/mode/monitoring/KafkaSignalProcessorSupport.java b/src/main/java/ru/nbch/credit_tracker/service/mode/monitoring/KafkaSignalProcessorSupport.java new file mode 100644 index 0000000..85d9840 --- /dev/null +++ b/src/main/java/ru/nbch/credit_tracker/service/mode/monitoring/KafkaSignalProcessorSupport.java @@ -0,0 +1,132 @@ +package ru.nbch.credit_tracker.service.mode.monitoring; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; +import ru.nbch.credit_tracker.entities.app.Hit; +import ru.nbch.credit_tracker.entities.external_request.kafka.PackageMessage; +import ru.nbch.credit_tracker.model.IUserPackageData; +import ru.nbch.credit_tracker.model.SignalKafkaEvent; +import ru.nbch.credit_tracker.service.nbch.SourceService; +import ru.nbch.credit_tracker.utils.CTUtil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Slf4j +@Component +public class KafkaSignalProcessorSupport { + + private final SourceService sourceService; + private final SignalKafkaEventPublisher eventPublisher; + + public KafkaSignalProcessorSupport(SourceService sourceService, + SignalKafkaEventPublisher eventPublisher) { + this.sourceService = sourceService; + this.eventPublisher = eventPublisher; + } + + public List process(List messages, + Map segmentMap, + Function, List> mappingLoader, + Function fidExtractor, + Function keyExtractor, + Function, Map>> packageDataLoader, + SignalEventBuilder eventBuilder, + SignalHitBuilder hitBuilder) { + List hits = new ArrayList<>(); + + List fids = messages.stream().map(PackageMessage::getFid).collect(Collectors.toList()); + List memberCodes = messages.stream() + .map(message -> message.getMemberCode().substring(0, 6)) + .toList(); + + List mappings = mappingLoader.apply(fids); + Map> mappingsByFid = mappings.stream() + .collect(Collectors.groupingBy(fidExtractor)); + Map> packageDataByKey = packageDataLoader.apply(mappings); + + // прелоад по memberCode категорий + Map busCategories = sourceService.findBusCategories(memberCodes); + + for (PackageMessage message : messages) { + Integer fid = message.getFid(); + String commonMemberCode = message.getMemberCode().substring(0, 6); + + String busCategory = busCategories.get(commonMemberCode); + if (StringUtils.isBlank(busCategory)) { + log.error("Для memberсode = {} отсутствует bus_category или не найден memberсode", commonMemberCode); + continue; + } + + int signalType = CTUtil.checkBusCategory(busCategory); + + List messageMappings = mappingsByFid.get(fid); + if (messageMappings == null) { + continue; + } + + for (M mapping : messageMappings) { + List packageDataList = packageDataByKey.get(keyExtractor.apply(mapping)); + if (packageDataList == null) { + continue; + } + + for (D packageData : packageDataList) { + if (!hasSignalType(packageData.getSignalTypes(), signalType)) { + continue; + } + + Integer segment = segmentMap.get(commonMemberCode); + SignalKafkaEvent event = eventBuilder.build(message, mapping, packageData, signalType, busCategory, segment); + + String reportKey = packageData.getUserId().substring(0, 6) + + "_" + packageData.getPackageName(); + String reportFileName = eventPublisher.resolveNameAndEnqueue(reportKey, event); + if (reportFileName == null) { + continue; // событие не встало в очередь — hit не пишем + } + + hits.add(hitBuilder.build(message, packageData, signalType, busCategory, segment, reportFileName)); + } + } + } + + return hits; + } + + private boolean hasSignalType(String signalTypes, int signalType) { + if (StringUtils.isBlank(signalTypes)) { + return false; + } + + String expectedSignalType = Integer.toString(signalType); + return Arrays.stream(signalTypes.split(",")) + .map(String::trim) + .anyMatch(expectedSignalType::equals); + } + + @FunctionalInterface + public interface SignalEventBuilder { + SignalKafkaEvent build(PackageMessage message, + M mapping, + D packageData, + int signalType, + String busCategory, + Integer segment); + } + + @FunctionalInterface + public interface SignalHitBuilder { + Hit build(PackageMessage message, + D packageData, + int signalType, + String busCategory, + Integer segment, + String reportFileName); + } +}