1、优化

This commit is contained in:
2026-05-08 10:33:03 +08:00
parent f50dd02b7b
commit cb180a8771
2 changed files with 164 additions and 107 deletions

View File

@@ -47,13 +47,13 @@ public class BimController {
}
@GetMapping("/progressData")
public Map<String, Object> getProgressData() {
return progressDataService.getOrCreateTask();
public Map<String, Object> getProgressData(@RequestParam String date) {
return progressDataService.getOrCreateTask(date);
}
@GetMapping("/progressData/{taskId}")
public Map<String, Object> getProgressDataResult(@PathVariable String taskId) {
return progressDataService.getTaskResult(taskId);
@GetMapping("/progressData/result")
public Map<String, Object> getProgressDataResult(@RequestParam String date) {
return progressDataService.getTaskResultByDate(date);
}
@PostMapping("/getPjDayListByPositionId")

View File

@@ -1,36 +1,34 @@
package com.bim.api.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bim.api.entity.ActAmtResponse;
import com.bim.api.entity.PartCodeRelation;
import com.bim.api.entity.PjDayListResponse;
import com.bim.api.query.ProjectProgressParams;
import com.bim.api.mapper.PartCodeRelationMapper;
import com.bim.api.util.ThirdPartyAuthUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import jakarta.annotation.PostConstruct;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class ProgressDataService extends ServiceImpl<PartCodeRelationMapper, PartCodeRelation> {
private static final String PROJECT_ID = "5e4bde33ec084f1a8673eb59b190dce7";
private static final String KEY_TASK_STATUS = "progress:task:";
private static final String KEY_TASK_TOTAL = ":total";
private static final String KEY_TASK_CURRENT = ":current";
private static final String KEY_TASK_RESULT = ":result";
private static final String KEY_PROCESSING = "progress:processing";
private static final String KEY_COMPLETED = "progress:completed";
private static final String KEY_LATEST_TASK = "progress:latest:taskId";
private static final Map<String, String> TASK_STATUS_CACHE = new ConcurrentHashMap<>();
private static final String KEY_TASK_PREFIX = "progress:task:";
private static final String KEY_PROCESSING_PREFIX = "progress:processing:";
private static final String SUFFIX_STATUS = ":status";
private static final String SUFFIX_TOTAL = ":total";
private static final String SUFFIX_CURRENT = ":current";
private static final String SUFFIX_RESULT = ":result";
private static final String SUFFIX_ERROR = ":error";
private static final String SUFFIX_RAW_ACT_AMT = ":rawActAmt";
private final ThirdPartyAuthUtil thirdPartyAuthUtil;
private final RedisTemplate<String, Object> redisTemplate;
@@ -40,49 +38,52 @@ public class ProgressDataService extends ServiceImpl<PartCodeRelationMapper, Par
this.redisTemplate = redisTemplate;
}
public Map<String, Object> getOrCreateTask() {
public Map<String, Object> getOrCreateTask(String date) {
String normalizedDate = normalizeDate(date);
Map<String, Object> result = new HashMap<>();
result.put("date", normalizedDate);
String latestTaskId = (String) redisTemplate.opsForValue().get(KEY_LATEST_TASK);
if (latestTaskId != null) {
String status = getTaskStatus(latestTaskId);
if ("COMPLETED".equals(status)) {
result.put("taskId", latestTaskId);
result.put("status", "COMPLETED");
return result;
}
String status = getTaskStatusByDate(normalizedDate);
if ("COMPLETED".equals(status)) {
result.put("status", "COMPLETED");
return result;
}
String processingTaskId = (String) redisTemplate.opsForValue().get(KEY_PROCESSING);
if (processingTaskId != null) {
result.put("taskId", processingTaskId);
String processing = (String) redisTemplate.opsForValue().get(buildProcessingKey(normalizedDate));
if (processing != null) {
result.put("status", "PROCESSING");
return result;
}
String taskId = UUID.randomUUID().toString().replace("-", "");
initTask(taskId);
calculateProgressAsync(taskId);
Boolean lockResult = redisTemplate.opsForValue().setIfAbsent(buildProcessingKey(normalizedDate), "1");
if (!Boolean.TRUE.equals(lockResult)) {
result.put("status", "PROCESSING");
return result;
}
initTask(normalizedDate);
calculateProgressAsync(normalizedDate);
result.put("taskId", taskId);
result.put("status", "STARTED");
return result;
}
public Map<String, Object> getTaskResult(String taskId) {
public Map<String, Object> getTaskResultByDate(String date) {
String normalizedDate = normalizeDate(date);
Map<String, Object> result = new HashMap<>();
result.put("date", normalizedDate);
String status = getTaskStatus(taskId);
result.put("taskId", taskId);
String status = getTaskStatusByDate(normalizedDate);
result.put("status", status);
if (status == null) {
result.put("status", "NOT_FOUND");
String processing = (String) redisTemplate.opsForValue().get(buildProcessingKey(normalizedDate));
result.put("status", processing != null ? "PROCESSING" : "NOT_FOUND");
return result;
}
Integer total = (Integer) redisTemplate.opsForValue().get(KEY_TASK_STATUS + taskId + KEY_TASK_TOTAL);
Integer current = (Integer) redisTemplate.opsForValue().get(KEY_TASK_STATUS + taskId + KEY_TASK_CURRENT);
Integer total = (Integer) redisTemplate.opsForValue().get(buildTaskKey(normalizedDate, SUFFIX_TOTAL));
Integer current = (Integer) redisTemplate.opsForValue().get(buildTaskKey(normalizedDate, SUFFIX_CURRENT));
result.put("total", total != null ? total : 0);
result.put("current", current != null ? current : 0);
@@ -94,35 +95,74 @@ public class ProgressDataService extends ServiceImpl<PartCodeRelationMapper, Par
result.put("progress", progress);
if ("COMPLETED".equals(status)) {
Object data = redisTemplate.opsForValue().get(KEY_TASK_STATUS + taskId + KEY_TASK_RESULT);
Object data = redisTemplate.opsForValue().get(buildTaskKey(normalizedDate, SUFFIX_RESULT));
result.put("data", data);
}
if ("FAILED".equals(status)) {
Object error = redisTemplate.opsForValue().get(buildTaskKey(normalizedDate, SUFFIX_ERROR));
if (error != null) {
result.put("error", error);
}
}
return result;
}
private String getTaskStatus(String taskId) {
if (taskId == null) return null;
return TASK_STATUS_CACHE.get(taskId);
private String normalizeDate(String date) {
if (date == null || date.isBlank()) {
throw new IllegalArgumentException("date cannot be blank, expected format: yyyy-MM-dd");
}
try {
return LocalDate.parse(date).toString();
} catch (DateTimeParseException e) {
throw new IllegalArgumentException("invalid date format, expected: yyyy-MM-dd");
}
}
private void initTask(String taskId) {
TASK_STATUS_CACHE.put(taskId, "STARTED");
redisTemplate.opsForValue().set(KEY_PROCESSING, taskId);
private String buildTaskKey(String date, String suffix) {
return KEY_TASK_PREFIX + date + suffix;
}
private void calculateProgressAsync(String taskId) {
TASK_STATUS_CACHE.put(taskId, "PROCESSING");
private String buildProcessingKey(String date) {
return KEY_PROCESSING_PREFIX + date;
}
private String getTaskStatusByDate(String date) {
return (String) redisTemplate.opsForValue().get(buildTaskKey(date, SUFFIX_STATUS));
}
private Map<String, Object> buildActAmtRequest(String projectId, String positionId, String period) {
Map<String, Object> request = new HashMap<>();
request.put("projectId", projectId);
request.put("positionId", positionId);
request.put("period", period);
return request;
}
private void initTask(String date) {
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_STATUS), "STARTED");
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_TOTAL), 0);
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_CURRENT), 0);
redisTemplate.delete(buildTaskKey(date, SUFFIX_RESULT));
redisTemplate.delete(buildTaskKey(date, SUFFIX_ERROR));
redisTemplate.delete(buildTaskKey(date, SUFFIX_RAW_ACT_AMT));
}
private void calculateProgressAsync(String date) {
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_STATUS), "PROCESSING");
new Thread(() -> {
try {
List<PartCodeRelation> relations = list();
int total = relations.size();
redisTemplate.opsForValue().set(KEY_TASK_STATUS + taskId + KEY_TASK_TOTAL, total);
redisTemplate.opsForValue().set(KEY_TASK_STATUS + taskId + KEY_TASK_CURRENT, 0);
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_TOTAL), total);
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_CURRENT), 0);
List<Map<String, Object>> results = new ArrayList<>();
List<Map<String, Object>> rawActAmtResults = new ArrayList<>();
int current = 0;
for (PartCodeRelation relation : relations) {
Map<String, Object> item = new HashMap<>();
@@ -131,49 +171,66 @@ public class ProgressDataService extends ServiceImpl<PartCodeRelationMapper, Par
try {
LocalDateTime createTime = relation.getCreateTime();
String period = createTime != null ? createTime.toString().replace("T", " ") : null;
String originalPeriod = createTime != null ? createTime.toString().replace("T", " ") : null;
String positionId = relation.getPartId();
String requestPeriod = date;
ProjectProgressParams params = new ProjectProgressParams();
params.setProjectId(PROJECT_ID);
params.setPositionIds(relation.getPartId());
params.setPeriod(period);
ActAmtResponse actAmtResponse = thirdPartyAuthUtil.findActAmtByPositionId(
PROJECT_ID,
positionId,
requestPeriod
);
PjDayListResponse pjDayResponse = thirdPartyAuthUtil.findPjDayListByPositionId(params);
Map<String, Object> requestParams = new HashMap<>();
requestParams.put("projectId", PROJECT_ID);
requestParams.put("positionId", positionId);
requestParams.put("period", requestPeriod);
Map<String, Object> rawEntry = new HashMap<>();
rawEntry.put("partId", positionId);
rawEntry.put("period", requestPeriod);
rawEntry.put("originalPeriod", originalPeriod);
rawEntry.put("request", requestParams);
rawEntry.put("response", actAmtResponse);
rawActAmtResults.add(rawEntry);
double progressData = 0;
if (pjDayResponse != null && pjDayResponse.getData() != null && !pjDayResponse.getData().isEmpty()) {
PjDayListResponse.PjDayData dayData = pjDayResponse.getData().get(0);
Double totalNum = dayData.getMeteringNum();
Double meteringNum = dayData.getMeteringAmt();
if (actAmtResponse != null && actAmtResponse.getData() != null && !actAmtResponse.getData().isEmpty()) {
ActAmtResponse.ActAmtData dayData = actAmtResponse.getData().get(0);
Double actAmt = dayData.getActAmt();
Double meteringAmt = dayData.getMeteringAmt();
if (totalNum != null && meteringNum != null && meteringNum != 0) {
progressData = totalNum / meteringNum;
if (actAmt != null && meteringAmt != null && meteringAmt != 0) {
progressData = actAmt / meteringAmt;
}
}
item.put("progressData", progressData);
} catch (Exception e) {
item.put("progressData", 0);
item.put("error", e.getMessage());
Map<String, Object> rawEntry = new HashMap<>();
rawEntry.put("partId", relation.getPartId());
rawEntry.put("request", buildActAmtRequest(PROJECT_ID, relation.getPartId(), date));
rawEntry.put("error", e.getMessage());
rawActAmtResults.add(rawEntry);
}
results.add(item);
Integer current = (Integer) redisTemplate.opsForValue().get(KEY_TASK_STATUS + taskId + KEY_TASK_CURRENT);
redisTemplate.opsForValue().set(KEY_TASK_STATUS + taskId + KEY_TASK_CURRENT, current + 1);
current++;
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_CURRENT), current);
}
redisTemplate.opsForValue().set(KEY_TASK_STATUS + taskId + KEY_TASK_RESULT, results);
redisTemplate.opsForValue().set(KEY_TASK_STATUS + taskId + KEY_TASK_CURRENT, total);
redisTemplate.delete(KEY_PROCESSING);
redisTemplate.opsForValue().set(KEY_COMPLETED, taskId);
redisTemplate.opsForValue().set(KEY_LATEST_TASK, taskId);
TASK_STATUS_CACHE.put(taskId, "COMPLETED");
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_RESULT), results);
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_RAW_ACT_AMT), rawActAmtResults);
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_CURRENT), total);
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_STATUS), "COMPLETED");
redisTemplate.delete(buildProcessingKey(date));
} catch (Exception e) {
TASK_STATUS_CACHE.put(taskId, "FAILED");
redisTemplate.delete(KEY_PROCESSING);
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_STATUS), "FAILED");
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_ERROR), e.getMessage());
redisTemplate.delete(buildProcessingKey(date));
}
}).start();
}