1、优化
This commit is contained in:
@@ -47,13 +47,13 @@ public class BimController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/progressData")
|
@GetMapping("/progressData")
|
||||||
public Map<String, Object> getProgressData() {
|
public Map<String, Object> getProgressData(@RequestParam String date) {
|
||||||
return progressDataService.getOrCreateTask();
|
return progressDataService.getOrCreateTask(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/progressData/{taskId}")
|
@GetMapping("/progressData/result")
|
||||||
public Map<String, Object> getProgressDataResult(@PathVariable String taskId) {
|
public Map<String, Object> getProgressDataResult(@RequestParam String date) {
|
||||||
return progressDataService.getTaskResult(taskId);
|
return progressDataService.getTaskResultByDate(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/getPjDayListByPositionId")
|
@PostMapping("/getPjDayListByPositionId")
|
||||||
|
|||||||
@@ -1,36 +1,34 @@
|
|||||||
package com.bim.api.service;
|
package com.bim.api.service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
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.PartCodeRelation;
|
||||||
import com.bim.api.entity.PjDayListResponse;
|
|
||||||
import com.bim.api.query.ProjectProgressParams;
|
|
||||||
import com.bim.api.mapper.PartCodeRelationMapper;
|
import com.bim.api.mapper.PartCodeRelationMapper;
|
||||||
import com.bim.api.util.ThirdPartyAuthUtil;
|
import com.bim.api.util.ThirdPartyAuthUtil;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
|
||||||
import org.springframework.stereotype.Service;
|
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.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.time.format.DateTimeParseException;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class ProgressDataService extends ServiceImpl<PartCodeRelationMapper, PartCodeRelation> {
|
public class ProgressDataService extends ServiceImpl<PartCodeRelationMapper, PartCodeRelation> {
|
||||||
|
|
||||||
private static final String PROJECT_ID = "5e4bde33ec084f1a8673eb59b190dce7";
|
private static final String PROJECT_ID = "5e4bde33ec084f1a8673eb59b190dce7";
|
||||||
|
|
||||||
private static final String KEY_TASK_STATUS = "progress:task:";
|
private static final String KEY_TASK_PREFIX = "progress:task:";
|
||||||
private static final String KEY_TASK_TOTAL = ":total";
|
private static final String KEY_PROCESSING_PREFIX = "progress:processing:";
|
||||||
private static final String KEY_TASK_CURRENT = ":current";
|
private static final String SUFFIX_STATUS = ":status";
|
||||||
private static final String KEY_TASK_RESULT = ":result";
|
private static final String SUFFIX_TOTAL = ":total";
|
||||||
private static final String KEY_PROCESSING = "progress:processing";
|
private static final String SUFFIX_CURRENT = ":current";
|
||||||
private static final String KEY_COMPLETED = "progress:completed";
|
private static final String SUFFIX_RESULT = ":result";
|
||||||
private static final String KEY_LATEST_TASK = "progress:latest:taskId";
|
private static final String SUFFIX_ERROR = ":error";
|
||||||
|
private static final String SUFFIX_RAW_ACT_AMT = ":rawActAmt";
|
||||||
private static final Map<String, String> TASK_STATUS_CACHE = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
private final ThirdPartyAuthUtil thirdPartyAuthUtil;
|
private final ThirdPartyAuthUtil thirdPartyAuthUtil;
|
||||||
private final RedisTemplate<String, Object> redisTemplate;
|
private final RedisTemplate<String, Object> redisTemplate;
|
||||||
@@ -40,49 +38,52 @@ public class ProgressDataService extends ServiceImpl<PartCodeRelationMapper, Par
|
|||||||
this.redisTemplate = redisTemplate;
|
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<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("date", normalizedDate);
|
||||||
|
|
||||||
String latestTaskId = (String) redisTemplate.opsForValue().get(KEY_LATEST_TASK);
|
String status = getTaskStatusByDate(normalizedDate);
|
||||||
if (latestTaskId != null) {
|
if ("COMPLETED".equals(status)) {
|
||||||
String status = getTaskStatus(latestTaskId);
|
result.put("status", "COMPLETED");
|
||||||
if ("COMPLETED".equals(status)) {
|
return result;
|
||||||
result.put("taskId", latestTaskId);
|
|
||||||
result.put("status", "COMPLETED");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String processingTaskId = (String) redisTemplate.opsForValue().get(KEY_PROCESSING);
|
String processing = (String) redisTemplate.opsForValue().get(buildProcessingKey(normalizedDate));
|
||||||
if (processingTaskId != null) {
|
if (processing != null) {
|
||||||
result.put("taskId", processingTaskId);
|
|
||||||
result.put("status", "PROCESSING");
|
result.put("status", "PROCESSING");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
String taskId = UUID.randomUUID().toString().replace("-", "");
|
Boolean lockResult = redisTemplate.opsForValue().setIfAbsent(buildProcessingKey(normalizedDate), "1");
|
||||||
initTask(taskId);
|
if (!Boolean.TRUE.equals(lockResult)) {
|
||||||
calculateProgressAsync(taskId);
|
result.put("status", "PROCESSING");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
initTask(normalizedDate);
|
||||||
|
calculateProgressAsync(normalizedDate);
|
||||||
|
|
||||||
result.put("taskId", taskId);
|
|
||||||
result.put("status", "STARTED");
|
result.put("status", "STARTED");
|
||||||
return result;
|
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<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("date", normalizedDate);
|
||||||
|
|
||||||
String status = getTaskStatus(taskId);
|
String status = getTaskStatusByDate(normalizedDate);
|
||||||
result.put("taskId", taskId);
|
|
||||||
result.put("status", status);
|
result.put("status", status);
|
||||||
|
|
||||||
if (status == null) {
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer total = (Integer) redisTemplate.opsForValue().get(KEY_TASK_STATUS + taskId + KEY_TASK_TOTAL);
|
Integer total = (Integer) redisTemplate.opsForValue().get(buildTaskKey(normalizedDate, SUFFIX_TOTAL));
|
||||||
Integer current = (Integer) redisTemplate.opsForValue().get(KEY_TASK_STATUS + taskId + KEY_TASK_CURRENT);
|
Integer current = (Integer) redisTemplate.opsForValue().get(buildTaskKey(normalizedDate, SUFFIX_CURRENT));
|
||||||
|
|
||||||
result.put("total", total != null ? total : 0);
|
result.put("total", total != null ? total : 0);
|
||||||
result.put("current", current != null ? current : 0);
|
result.put("current", current != null ? current : 0);
|
||||||
@@ -94,35 +95,74 @@ public class ProgressDataService extends ServiceImpl<PartCodeRelationMapper, Par
|
|||||||
result.put("progress", progress);
|
result.put("progress", progress);
|
||||||
|
|
||||||
if ("COMPLETED".equals(status)) {
|
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);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTaskStatus(String taskId) {
|
private String normalizeDate(String date) {
|
||||||
if (taskId == null) return null;
|
if (date == null || date.isBlank()) {
|
||||||
return TASK_STATUS_CACHE.get(taskId);
|
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) {
|
private String buildTaskKey(String date, String suffix) {
|
||||||
TASK_STATUS_CACHE.put(taskId, "STARTED");
|
return KEY_TASK_PREFIX + date + suffix;
|
||||||
redisTemplate.opsForValue().set(KEY_PROCESSING, taskId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calculateProgressAsync(String taskId) {
|
private String buildProcessingKey(String date) {
|
||||||
TASK_STATUS_CACHE.put(taskId, "PROCESSING");
|
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(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
List<PartCodeRelation> relations = list();
|
List<PartCodeRelation> relations = list();
|
||||||
int total = relations.size();
|
int total = relations.size();
|
||||||
|
|
||||||
redisTemplate.opsForValue().set(KEY_TASK_STATUS + taskId + KEY_TASK_TOTAL, total);
|
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_TOTAL), total);
|
||||||
redisTemplate.opsForValue().set(KEY_TASK_STATUS + taskId + KEY_TASK_CURRENT, 0);
|
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_CURRENT), 0);
|
||||||
|
|
||||||
List<Map<String, Object>> results = new ArrayList<>();
|
List<Map<String, Object>> results = new ArrayList<>();
|
||||||
|
List<Map<String, Object>> rawActAmtResults = new ArrayList<>();
|
||||||
|
int current = 0;
|
||||||
|
|
||||||
for (PartCodeRelation relation : relations) {
|
for (PartCodeRelation relation : relations) {
|
||||||
Map<String, Object> item = new HashMap<>();
|
Map<String, Object> item = new HashMap<>();
|
||||||
@@ -131,49 +171,66 @@ public class ProgressDataService extends ServiceImpl<PartCodeRelationMapper, Par
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
LocalDateTime createTime = relation.getCreateTime();
|
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();
|
ActAmtResponse actAmtResponse = thirdPartyAuthUtil.findActAmtByPositionId(
|
||||||
params.setProjectId(PROJECT_ID);
|
PROJECT_ID,
|
||||||
params.setPositionIds(relation.getPartId());
|
positionId,
|
||||||
params.setPeriod(period);
|
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;
|
double progressData = 0;
|
||||||
if (pjDayResponse != null && pjDayResponse.getData() != null && !pjDayResponse.getData().isEmpty()) {
|
if (actAmtResponse != null && actAmtResponse.getData() != null && !actAmtResponse.getData().isEmpty()) {
|
||||||
PjDayListResponse.PjDayData dayData = pjDayResponse.getData().get(0);
|
ActAmtResponse.ActAmtData dayData = actAmtResponse.getData().get(0);
|
||||||
Double totalNum = dayData.getMeteringNum();
|
Double actAmt = dayData.getActAmt();
|
||||||
Double meteringNum = dayData.getMeteringAmt();
|
Double meteringAmt = dayData.getMeteringAmt();
|
||||||
|
|
||||||
if (totalNum != null && meteringNum != null && meteringNum != 0) {
|
if (actAmt != null && meteringAmt != null && meteringAmt != 0) {
|
||||||
progressData = totalNum / meteringNum;
|
progressData = actAmt / meteringAmt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item.put("progressData", progressData);
|
item.put("progressData", progressData);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
item.put("progressData", 0);
|
item.put("progressData", 0);
|
||||||
item.put("error", e.getMessage());
|
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);
|
results.add(item);
|
||||||
|
current++;
|
||||||
Integer current = (Integer) redisTemplate.opsForValue().get(KEY_TASK_STATUS + taskId + KEY_TASK_CURRENT);
|
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_CURRENT), current);
|
||||||
redisTemplate.opsForValue().set(KEY_TASK_STATUS + taskId + KEY_TASK_CURRENT, current + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
redisTemplate.opsForValue().set(KEY_TASK_STATUS + taskId + KEY_TASK_RESULT, results);
|
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_RESULT), results);
|
||||||
redisTemplate.opsForValue().set(KEY_TASK_STATUS + taskId + KEY_TASK_CURRENT, total);
|
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_RAW_ACT_AMT), rawActAmtResults);
|
||||||
|
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_CURRENT), total);
|
||||||
redisTemplate.delete(KEY_PROCESSING);
|
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_STATUS), "COMPLETED");
|
||||||
redisTemplate.opsForValue().set(KEY_COMPLETED, taskId);
|
redisTemplate.delete(buildProcessingKey(date));
|
||||||
redisTemplate.opsForValue().set(KEY_LATEST_TASK, taskId);
|
|
||||||
|
|
||||||
TASK_STATUS_CACHE.put(taskId, "COMPLETED");
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
TASK_STATUS_CACHE.put(taskId, "FAILED");
|
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_STATUS), "FAILED");
|
||||||
redisTemplate.delete(KEY_PROCESSING);
|
redisTemplate.opsForValue().set(buildTaskKey(date, SUFFIX_ERROR), e.getMessage());
|
||||||
|
redisTemplate.delete(buildProcessingKey(date));
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user