1、优化
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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);
|
||||
String status = getTaskStatusByDate(normalizedDate);
|
||||
if ("COMPLETED".equals(status)) {
|
||||
result.put("taskId", latestTaskId);
|
||||
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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user