Update sql for fids finding; Minor refactoring; Optimize searching for passport data

This commit is contained in:
Mikhail Trofimov 2025-07-07 16:34:45 +03:00
parent fecb4d467f
commit f0d5381b64
7 changed files with 42 additions and 27 deletions

View file

@ -2,6 +2,7 @@ package ru.nbch.credit_tracker.config.rest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.web.client.RestTemplate;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
@ -21,6 +22,6 @@ public class RestConfig {
@Bean(name = "executorService")
public ExecutorService executorService() {
return Executors.newCachedThreadPool();
return Executors.newCachedThreadPool(new CustomizableThreadFactory("package-registration-"));
}
}

View file

@ -11,6 +11,7 @@ import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.dto.UserPackage;
import ru.nbch.credit_tracker.entities.request.active_packages.MonitoringActivePackagesRequest;
import ru.nbch.credit_tracker.entities.request.monitoring_request.MonitoringRequest;
import ru.nbch.credit_tracker.entities.request.monitoring_request.Subject;
import ru.nbch.credit_tracker.entities.response.active_packages.MonitoringActivePackagesResponse;
import ru.nbch.credit_tracker.entities.response.active_packages.Package;
import ru.nbch.credit_tracker.entities.response.active_packages.Packages;
@ -142,6 +143,7 @@ public class SignalFacade {
}
packageId = signalService.registerPackage(monitoringRequest);
log.info("Package registered. PackageId {}. Status: {}", packageId, Status.PROCESSING.name());
} catch (Exception e) {
if (e instanceof SignalClientException) {
throw (SignalClientException) e;
@ -150,15 +152,16 @@ public class SignalFacade {
throw serverExcp(SignalError.ERROR_100, XmlErrorFormat.MonitoringError);
}
// в отдельном потоке запускаем поиск фидов и расчет флагов просрочек
registerFidsAndDebts(packageId, monitoringRequest.getPackageName());
// в отдельном потоке запускаем регистрацию субъектов, поиск фидов и расчет флагов просрочек
registerFidsAndDebts(packageId, monitoringRequest.getPackageName(), monitoringRequest.getSubjects().getSubject());
return ResponseEntity.ok().body(new MonitoringResponse());
}
private void registerFidsAndDebts(Integer packageId, String packageName) {
private void registerFidsAndDebts(Integer packageId, String packageName, List<Subject> subjects) {
executor.execute(() -> {
try {
signalService.registerSubjects(subjects, packageId);
List<PhoneService.FidsPhoneData> phoneFidsData = signalService.registerSubjectsFidAndDebts(packageId);
if (!phoneFidsData.isEmpty()) {
Signals signals = signalService.buildSignals(packageId, phoneFidsData);
@ -174,6 +177,7 @@ public class SignalFacade {
} catch (Exception e) {
signalService.updatePackageStatus(packageId, Status.ERROR);
log.error("Ошибка при поиске фидов или расчете флагов просрочек. Package_id {}", packageId, e);
// TODO очистить таблицу signals_phone_fid_map ?
}
});
}

View file

@ -1,6 +1,7 @@
package ru.nbch.credit_tracker.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.dto.Hit;
@ -50,7 +51,7 @@ public class MonitoringService {
}
public void run() {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new CustomizableThreadFactory("monitoring-"));
long period = config.getMonitoringInterval() != null ? config.getMonitoringInterval() : 15;
scheduler.scheduleAtFixedRate(this::monitor, 0, period, TimeUnit.MINUTES);
}

View file

@ -67,13 +67,17 @@ public class SignalService {
.createdAt(LocalDateTime.now())
.status(Status.PROCESSING.name())
.build();
Integer packageId = userPackageService.insertPackage(userPackage);
List<Subject> subjects = request.getSubjects().getSubject();
return userPackageService.insertPackage(userPackage);
}
public void registerSubjects(List<Subject> subjects, Integer packageId) {
log.info("Start registering subjects. PackageId: {}", packageId);
for (int i = 0; i < subjects.size(); i += batchSize) {
int end = Math.min(i + batchSize, subjects.size());
phoneFidMapService.registerSubjects(subjects.subList(i, end), packageId); // TODO преобразовывать список в List<PhoneFidMap> ?
phoneFidMapService.registerSubjects(subjects.subList(i, end), packageId);
log.trace("Registered subject's batch from: {} to: {}. Total count: {}. PackageId: {}", i, end, subjects.size(), packageId);
}
return packageId;
log.info("Subjects were registered. PackageId: {}", packageId);
}
public List<PhoneService.FidsPhoneData> registerSubjectsFidAndDebts(Integer packageId) {
@ -82,6 +86,7 @@ public class SignalService {
}
public List<PhoneService.FidsPhoneData> updateFlags(List<PhoneFidMap> subjects, Integer packageId) {
log.info("Start calculating fids and flags for subjects. PackageId: {}", packageId);
List<PhoneService.FidsPhoneData> fidsPhoneDataList = phoneService.findFidsPhoneData(subjects);
LocalDateTime calculatedAt = LocalDateTime.now();
for (int i = 0; i < fidsPhoneDataList.size(); i += batchSize) {
@ -120,9 +125,10 @@ public class SignalService {
for (int j = 0; j < subjectToUpdate.size(); j += updateBatchSize) {
int endIndex = Math.min(j + updateBatchSize, subjectToUpdate.size());
phoneFidMapService.updatePhoneFidMaps(subjectToUpdate.subList(j, endIndex));
log.trace("Updated fids and flags for subject's batch from: {} to: {}. Total count: {}. PackageId: {}", i, end, subjectToUpdate.size(), packageId);
}
}
log.info("Finish calculating fids and flags for subjects. PackageId: {}", packageId);
return fidsPhoneDataList;
}

View file

@ -1,6 +1,7 @@
package ru.nbch.credit_tracker.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
@ -36,7 +37,7 @@ public class UpdatingFlagsService {
}
public void run() {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new CustomizableThreadFactory("updating-flags-"));
scheduler.scheduleAtFixedRate(this::update, 0, updateFlagsInterval, TimeUnit.DAYS);
}

View file

@ -70,20 +70,21 @@ public class PersonService {
}
private Map<Integer, PassportData> findPassportData(List<Integer> fids) {
Map<Integer, PassportData> passportDataMap = new HashMap<>();
Map<Integer, PassportData> resultMap = new HashMap<>();
List<PassportData> passports = mapper.findPassportData(fids);
Map<Integer, List<PassportData>> passportsMap = passports.stream()
.collect(Collectors.groupingBy(PassportData::getFid));
fids.forEach(fid -> {
PassportData passport = findPassport(passports.stream()
.filter(passportData -> passportData.getFid().equals(fid))
.collect(Collectors.toList()));
PassportData passport = findPassport(passportsMap.get(fid));
if (passport != null) {
passportDataMap.put(fid, passport);
resultMap.put(fid, passport);
}
});
return passportDataMap;
return resultMap;
}
private PassportData findPassport(List<PassportData> passports) {

View file

@ -6,18 +6,19 @@
<mapper namespace="ru.nbch.credit_tracker.mapper.indic.PhoneMapper">
<resultMap id="fidsDataResultMap" type="ru.nbch.credit_tracker.service.indic.PhoneService$FidsData">
<result property="phone" column="NUMBER" />
<result property="fid" column="FID" />
<result property="fileSinceDate" column="FILE_SINCE_DT" />
<result property="phone" column="number" />
<result property="fid" column="fid" />
<result property="fileSinceDate" column="fileSinceDate" />
</resultMap>
<select id="findFids" resultMap="fidsDataResultMap">
SELECT NUMBER, FID, FILE_SINCE_DT
FROM PHONE_NORM
WHERE NUMBER in
<foreach item="phone" collection="phones" open="(" separator="," close=")">
#{phone}
</foreach>
ORDER BY FILE_SINCE_DT DESC, FID DESC
SELECT pn.NUMBER AS number, pn.FID AS fid, pn.FILE_SINCE_DT AS fileSinceDate
FROM PHONE_NORM pn
INNER JOIN NAME n ON n.FID = pn.FID
WHERE number in
<foreach item="phone" collection="phones" open="(" separator="," close=")">
#{phone}
</foreach>
ORDER BY fileSinceDate DESC, fid DESC
</select>
</mapper>