SUPPORT-9213: перенес логику ip адресов в процессор, добавил подписку на топик связи для ip

This commit is contained in:
adel.ka 2025-06-19 13:13:38 +03:00
parent a4edcc4f70
commit 8736374a13
7 changed files with 210 additions and 94 deletions

View file

@ -28,6 +28,13 @@ public class IpDirectoryDao extends AbstractDataDao<IpDirectoryRecord> {
deleteByFieldInValues(Tables.IP_DIRECTORY.IP_ADDRESS, ips);
}
public boolean exists(String ip) {
return dsl.fetchExists(
dsl.selectOne()
.from(IP_DIRECTORY)
.where(IP_DIRECTORY.IP_ADDRESS.eq(ip))
);
}
@Override
protected Table<IpDirectoryRecord> getTable() {
return IP_DIRECTORY;

View file

@ -2,9 +2,11 @@ package ru.micord.ervu.account_applications.dao;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jooq.DSLContext;
import org.jooq.Field;
import org.jooq.Table;
import org.springframework.stereotype.Repository;
import ru.micord.ervu.account_applications.db_beans.public_.Tables;
@ -19,6 +21,19 @@ public class RecruitmentIpDao extends AbstractDataDao<RecruitmentIpRecord> {
super(dsl);
}
public boolean existsIpAddress(String ip) {
return !getExistingIpAddresses(List.of(ip)).isEmpty();
}
public void deleteRecruitmentIp(RecruitmentIpRecord record) {
Map<Field<String>, String> conditions = Map.of(
Tables.RECRUITMENT_IP.RECRUITMENT_ID, record.getRecruitmentId(),
Tables.RECRUITMENT_IP.IP_ADDRESS, record.getIpAddress()
);
deleteByValues(conditions);
}
public Set<String> getExistingIpAddresses(List<String> ips) {
return getExistingValuesByField(Tables.RECRUITMENT_IP.IP_ADDRESS, ips);
}

View file

@ -3,7 +3,12 @@ package ru.micord.ervu.account_applications.kafka;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
import ru.micord.ervu.account_applications.model.*;
import ru.micord.ervu.account_applications.model.RecruitmentData;
import ru.micord.ervu.account_applications.model.RecruitmentIpData;
import ru.micord.ervu.account_applications.model.RecruitmentSolutionData;
import ru.micord.ervu.account_applications.model.RoleData;
import ru.micord.ervu.account_applications.model.SolutionData;
import ru.micord.ervu.account_applications.model.SolutionRoleData;
import ru.micord.ervu.account_applications.service.ErvuDirectoriesService;
/**
@ -109,4 +114,14 @@ public class ErvuDirectoriesListener {
public void listenKafkaDomainSolutionDeleted(String kafkaMessage) {
ervuDirectoriesService.processDeleteLink(kafkaMessage, RecruitmentSolutionData.class);
}
@KafkaListener(id = "${kafka.domain_ip.created.group.id}", topics = "${kafka.domain_ip.created}")
public void listenKafkaDomainIpCreated(String kafkaMessage) {
ervuDirectoriesService.processUpsertMessage(kafkaMessage, RecruitmentIpData.class);
}
@KafkaListener(id = "${kafka.domain_ip.deleted.group.id}", topics = "${kafka.domain_ip.deleted}")
public void listenKafkaDomainIpDeleted(String kafkaMessage) {
ervuDirectoriesService.processDeleteLink(kafkaMessage, RecruitmentIpData.class);
}
}

View file

@ -0,0 +1,38 @@
package ru.micord.ervu.account_applications.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* @author Adel Kalimullin
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class RecruitmentIpData {
private String idDomain;
@JsonProperty("ip")
private String ipAddress;
public RecruitmentIpData(String idDomain, String ipAddress) {
this.idDomain = idDomain;
this.ipAddress = ipAddress;
}
public RecruitmentIpData() {
}
public String getIdDomain() {
return idDomain;
}
public void setIdDomain(String idDomain) {
this.idDomain = idDomain;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
}

View file

@ -1,88 +0,0 @@
package ru.micord.ervu.account_applications.service;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.stereotype.Component;
import ru.micord.ervu.account_applications.dao.IpDirectoryDao;
import ru.micord.ervu.account_applications.dao.RecruitmentIpDao;
import ru.micord.ervu.account_applications.db_beans.public_.tables.records.IpDirectoryRecord;
import ru.micord.ervu.account_applications.db_beans.public_.tables.records.RecruitmentIpRecord;
/**
* @author Adel Kalimullin
*/
@Component
public class RecruitmentIpService {
private final RecruitmentIpDao dao;
private final IpDirectoryDao ipDirectoryDao;
public RecruitmentIpService(RecruitmentIpDao dao, IpDirectoryDao ipDirectoryDao) {
this.dao = dao;
this.ipDirectoryDao = ipDirectoryDao;
}
public void upsertRecruitmentIpAddresses(String recruitmentId, Set<String> incomingIps) {
Set<String> existingIps = dao.getIpAddressesByRecruitmentId(recruitmentId);
Set<String> toAdd = new HashSet<>(incomingIps);
toAdd.removeAll(existingIps);
Set<String> toDelete = new HashSet<>(existingIps);
toDelete.removeAll(incomingIps);
handleDeletion(recruitmentId, toDelete);
handleInsertion(recruitmentId, toAdd);
}
private void handleDeletion(String recruitmentId, Set<String> toDelete) {
if (toDelete.isEmpty()) {
return;
}
dao.deleteRecruitmentIpsByRecruitmentIdAndIps(recruitmentId, List.copyOf(toDelete));
Set<String> stillUsedIps = dao.getExistingIpAddresses(List.copyOf(toDelete));
Set<String> toRemoveFromDirectory = toDelete.stream()
.filter(ip -> !stillUsedIps.contains(ip))
.collect(Collectors.toSet());
if (!toRemoveFromDirectory.isEmpty()) {
ipDirectoryDao.deleteByIpAddresses(List.copyOf(toRemoveFromDirectory));
}
}
private void handleInsertion(String recruitmentId, Set<String> toAdd) {
if (toAdd.isEmpty()){
return;
}
List<RecruitmentIpRecord> recordsToAdd = toAdd.stream()
.map(ip -> {
RecruitmentIpRecord record = dao.newRecord();
record.setRecruitmentId(recruitmentId);
record.setIpAddress(ip);
return record;
})
.toList();
dao.mergeRecords(recordsToAdd);
Set<String> existingDirectoryIps = ipDirectoryDao.getExistingIpAddresses(List.copyOf(toAdd));
Set<String> directoryToInsert = toAdd.stream()
.filter(ip -> !existingDirectoryIps.contains(ip))
.collect(Collectors.toSet());
if (!directoryToInsert.isEmpty()) {
List<IpDirectoryRecord> ipDirectoryRecords = directoryToInsert.stream()
.map(ip -> {
IpDirectoryRecord record = new IpDirectoryRecord();
record.setIpAddress(ip);
return record;
})
.toList();
ipDirectoryDao.mergeRecords(ipDirectoryRecords);
}
}
}

View file

@ -0,0 +1,130 @@
package ru.micord.ervu.account_applications.service.processor.impl;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.stereotype.Component;
import ru.micord.ervu.account_applications.dao.IpDirectoryDao;
import ru.micord.ervu.account_applications.dao.RecruitmentIpDao;
import ru.micord.ervu.account_applications.db_beans.public_.tables.records.IpDirectoryRecord;
import ru.micord.ervu.account_applications.db_beans.public_.tables.records.RecruitmentIpRecord;
import ru.micord.ervu.account_applications.model.RecruitmentIpData;
import ru.micord.ervu.account_applications.service.processor.LinkDataProcessor;
/**
* @author Adel Kalimullin
*/
@Component
public class RecruitmentIpProcessor
implements LinkDataProcessor<RecruitmentIpData, RecruitmentIpRecord> {
private final RecruitmentIpDao recruitmentIpDao;
private final IpDirectoryDao ipDirectoryDao;
public RecruitmentIpProcessor(RecruitmentIpDao recruitmentIpDao, IpDirectoryDao ipDirectoryDao) {
this.recruitmentIpDao = recruitmentIpDao;
this.ipDirectoryDao = ipDirectoryDao;
}
@Override
public void upsertData(RecruitmentIpData data) {
RecruitmentIpRecord record = mapToRecord(data);
recruitmentIpDao.upsertData(record);
String ip = data.getIpAddress();
boolean exists = ipDirectoryDao.exists(ip);
if (!exists) {
IpDirectoryRecord ipDirectoryRecord = ipDirectoryDao.newRecord();
ipDirectoryRecord.setIpAddress(ip);
ipDirectoryDao.upsertData(ipDirectoryRecord);
}
}
@Override
public void deleteLink(RecruitmentIpData data) {
RecruitmentIpRecord record = mapToRecord(data);
recruitmentIpDao.deleteRecruitmentIp(record);
String ip = data.getIpAddress();
boolean stillUsed = recruitmentIpDao.existsIpAddress(ip);
if (!stillUsed) {
ipDirectoryDao.deleteByIpAddresses(List.of(ip));
}
}
@Override
public void changeActiveStatus(String id, boolean active) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Class<RecruitmentIpData> getType() {
return RecruitmentIpData.class;
}
@Override
public RecruitmentIpRecord mapToRecord(RecruitmentIpData data) {
RecruitmentIpRecord record = recruitmentIpDao.newRecord();
record.setRecruitmentId(data.getIdDomain());
record.setIpAddress(data.getIpAddress());
return record;
}
public void upsertRecruitmentIpAddresses(String recruitmentId, Set<String> incomingIps) {
Set<String> existingIps = recruitmentIpDao.getIpAddressesByRecruitmentId(recruitmentId);
Set<String> toAdd = new HashSet<>(incomingIps);
toAdd.removeAll(existingIps);
Set<String> toDelete = new HashSet<>(existingIps);
toDelete.removeAll(incomingIps);
handleDeletion(recruitmentId, toDelete);
handleInsertion(recruitmentId, toAdd);
}
private void handleDeletion(String recruitmentId, Set<String> toDelete) {
if (toDelete.isEmpty()) {
return;
}
recruitmentIpDao.deleteRecruitmentIpsByRecruitmentIdAndIps(recruitmentId, List.copyOf(toDelete));
Set<String> stillUsedIps = recruitmentIpDao.getExistingIpAddresses(List.copyOf(toDelete));
Set<String> toRemoveFromDirectory = toDelete.stream()
.filter(ip -> !stillUsedIps.contains(ip))
.collect(Collectors.toSet());
if (!toRemoveFromDirectory.isEmpty()) {
ipDirectoryDao.deleteByIpAddresses(List.copyOf(toRemoveFromDirectory));
}
}
private void handleInsertion(String recruitmentId, Set<String> toAdd) {
if (toAdd.isEmpty()) {
return;
}
List<RecruitmentIpRecord> recordsToAdd = toAdd.stream()
.map(ip -> mapToRecord(new RecruitmentIpData(recruitmentId, ip)))
.toList();
recruitmentIpDao.mergeRecords(recordsToAdd);
Set<String> existingDirectoryIps = ipDirectoryDao.getExistingIpAddresses(List.copyOf(toAdd));
Set<String> directoryToInsert = toAdd.stream()
.filter(ip -> !existingDirectoryIps.contains(ip))
.collect(Collectors.toSet());
if (!directoryToInsert.isEmpty()) {
List<IpDirectoryRecord> ipDirectoryRecords = directoryToInsert.stream()
.map(ip -> {
IpDirectoryRecord record = ipDirectoryDao.newRecord();
record.setIpAddress(ip);
return record;
})
.toList();
ipDirectoryDao.mergeRecords(ipDirectoryRecords);
}
}
}

View file

@ -13,7 +13,6 @@ import ru.micord.ervu.account_applications.dao.RecruitmentDao;
import ru.micord.ervu.account_applications.db_beans.public_.tables.records.RecruitmentRecord;
import ru.micord.ervu.account_applications.model.RecruitmentData;
import ru.micord.ervu.account_applications.model.ReferenceEntity;
import ru.micord.ervu.account_applications.service.RecruitmentIpService;
import ru.micord.ervu.account_applications.service.processor.DataProcessor;
@ -24,14 +23,14 @@ import ru.micord.ervu.account_applications.service.processor.DataProcessor;
public class RecruitmentProcessor implements DataProcessor<RecruitmentData, RecruitmentRecord> {
private final RecruitmentDao dao;
private final RecruitmentSolutionProcessor recruitmentSolutionProcessor;
private final RecruitmentIpService recruitmentIpService;
private final RecruitmentIpProcessor recruitmentIpProcessor;
public RecruitmentProcessor(RecruitmentDao dao,
RecruitmentSolutionProcessor recruitmentSolutionProcessor,
RecruitmentIpService recruitmentIpService) {
RecruitmentIpProcessor recruitmentIpProcessor) {
this.dao = dao;
this.recruitmentSolutionProcessor = recruitmentSolutionProcessor;
this.recruitmentIpService = recruitmentIpService;
this.recruitmentIpProcessor = recruitmentIpProcessor;
}
@Override
@ -45,7 +44,7 @@ public class RecruitmentProcessor implements DataProcessor<RecruitmentData, Recr
recruitmentSolutionProcessor.upsertRecruitmentSolutions(data.getId(), solutionsIds);
}
if (!CollectionUtils.isEmpty(data.getIpAddresses())) {
recruitmentIpService.upsertRecruitmentIpAddresses(data.getId(), data.getIpAddresses());
recruitmentIpProcessor.upsertRecruitmentIpAddresses(data.getId(), data.getIpAddresses());
}
dao.upsertData(recruitmentRecord);