bug修复

This commit is contained in:
2025-02-05 11:28:50 +08:00
parent 0b861f0e21
commit 7892c0f5cc
21 changed files with 324 additions and 95 deletions

View File

@ -358,14 +358,17 @@ public class AppStatisticsServiceImpl implements AppStatisticsService {
//上一个周期的支付订单金额
vo.setPreviousOrderAmount(orderAmountDf.format(orderAmount));
// 计算预览_支付转化率
if(pay==0){
if(preview==0){
vo.setPreviousPreviewPay("0.00");
}else {
BigDecimal previewPay = new BigDecimal(pay).divide(new BigDecimal(preview), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
vo.setPreviousPreviewPay(df.format(previewPay));
}
if(scanCode==0){
vo.setPreviousScanCodePay("0.00");
}else {
BigDecimal previewPay = new BigDecimal(preview).divide(new BigDecimal(pay), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
vo.setNowPreviewPay(df.format(previewPay));
BigDecimal scanCodePay = new BigDecimal(scanCode).divide(new BigDecimal(pay), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
vo.setNowScanCodePay(df.format(scanCodePay));
BigDecimal scanCodePay = new BigDecimal(pay).divide(new BigDecimal(scanCode), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
vo.setPreviousScanCodePay(df.format(scanCodePay));
}
}
}

View File

@ -25,6 +25,8 @@ public interface TaskService {
void taskStart(Long taskId, WorkerAuthReqVo req);
void forceCreateTaskByFaceIdAndTempalteId(Long faceId, Long templateId);
void autoCreateTaskByFaceId(Long id);
Date getTaskShotDate(Long taskId);

View File

@ -3,6 +3,7 @@ package com.ycwl.basic.service.task.impl;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.facebody.model.v20191230.AddFaceEntityRequest;
import com.aliyuncs.facebody.model.v20191230.AddFaceRequest;
import com.aliyuncs.facebody.model.v20191230.AddFaceResponse;
@ -15,6 +16,7 @@ import com.aliyuncs.facebody.model.v20191230.ListFaceEntitiesRequest;
import com.aliyuncs.facebody.model.v20191230.ListFaceEntitiesResponse;
import com.aliyuncs.facebody.model.v20191230.SearchFaceRequest;
import com.aliyuncs.facebody.model.v20191230.SearchFaceResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ycwl.basic.biz.OrderBiz;
import com.ycwl.basic.config.FaceDetectConfig;
import com.ycwl.basic.constant.FaceConstant;
@ -33,12 +35,16 @@ import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
import com.ycwl.basic.model.pc.faceSample.req.FaceSampleReqQuery;
import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
import com.ycwl.basic.model.task.resp.AddFaceSampleRespVo;
import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
import com.ycwl.basic.ratelimiter.FixedRateLimiter;
import com.ycwl.basic.ratelimiter.SlidingWindowRateLimiter;
import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.task.TaskFaceService;
import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter;
@ -49,6 +55,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
@ -63,6 +70,7 @@ import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
@Slf4j
@ -87,11 +95,14 @@ public class TaskFaceServiceImpl implements TaskFaceService {
@Autowired
private OrderBiz orderBiz;
// 阿里云人脸检索限制qps=2
private final SlidingWindowRateLimiter addEntityLimiter = new SlidingWindowRateLimiter(1);
private final FixedRateLimiter addEntityLimiter = new FixedRateLimiter(600, TimeUnit.MILLISECONDS);
// 阿里云人脸检索限制qps=5
private final SlidingWindowRateLimiter searchFaceLimiter = new SlidingWindowRateLimiter(4);
private final SlidingWindowRateLimiter deleteDbLimiter = new SlidingWindowRateLimiter(1);
private final SlidingWindowRateLimiter deleteEntityLimiter = new SlidingWindowRateLimiter(1);
private final FixedRateLimiter searchFaceLimiter = new FixedRateLimiter(200, TimeUnit.MILLISECONDS);
private final FixedRateLimiter deleteDbLimiter = new FixedRateLimiter(600, TimeUnit.MILLISECONDS);
private final FixedRateLimiter deleteEntityLimiter = new FixedRateLimiter(600, TimeUnit.MILLISECONDS);
@Autowired
private ScenicRepository scenicRepository;
private IAcsClient getClient() {
DefaultProfile profile = DefaultProfile.getProfile(
@ -168,7 +179,7 @@ public class TaskFaceServiceImpl implements TaskFaceService {
// request.setQualityScoreThreshold(60f);
FaceDetectLog log = FaceDetectLog.quickCreate("预留字段", request);
try {
searchFaceLimiter.aquire();
searchFaceLimiter.acquire();
} catch (InterruptedException ignored) {
}
try {
@ -243,7 +254,7 @@ public class TaskFaceServiceImpl implements TaskFaceService {
request.setEntityId(entityId);
IAcsClient client = getClient();
try {
addEntityLimiter.aquire();
addEntityLimiter.acquire();
} catch (InterruptedException ignored) {
}
try {
@ -270,38 +281,67 @@ public class TaskFaceServiceImpl implements TaskFaceService {
@Override
public void batchDeleteExpiredFace(Long scenicId) {
FaceSampleReqQuery query = new FaceSampleReqQuery();
query.setDeviceId(scenicId);
faceSampleMapper.list(query);
ScenicConfigEntity scenicConfig = scenicMapper.getConfig(scenicId);
if (scenicConfig == null) {
return;
}
log.info("当前景区{},开始删除人脸样本", scenicId);
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
Integer sampleStoreDay = scenicConfig.getSampleStoreDay();
if (sampleStoreDay == null) {
sampleStoreDay = 3;
log.info("当前景区{},人脸样本保存天数未设置,默认7天", scenicId);
sampleStoreDay = 7;
}
Date thatDay = DateUtil.offsetDay(new Date(), -sampleStoreDay);
Date dayEnd = DateUtil.endOfDay(thatDay);
query.setEndTime(dayEnd);
IAcsClient client = getClient();
faceSampleMapper.list(query).forEach(faceSampleEntity -> {
String entityId = generateEntityId(faceSampleEntity);
DeleteFaceEntityRequest request = new DeleteFaceEntityRequest();
request.setDbName(scenicId.toString());
request.setEntityId(entityId);
try {
deleteEntityLimiter.aquire();
} catch (InterruptedException ignored) {
}
try {
client.getAcsResponse(request);
} catch (ClientException e) {
return;
} finally {
faceSampleMapper.deleteById(faceSampleEntity.getId());
Date endDate = DateUtils.addDateDays(new Date(), -(sampleStoreDay + 1));
List<FaceSampleEntity> faceSampleList = faceSampleMapper.listEntity(scenicId, endDate);
if (faceSampleList.isEmpty()) {
log.info("当前景区{},人脸样本为空", scenicId);
return;
}
faceSampleList.forEach(faceSample -> {
boolean success = deleteFaceSample(String.valueOf(scenicId), generateEntityId(faceSample));
if (success) {
log.info("当前景区{},人脸样本ID{},删除成功", scenicId, faceSample.getId());
faceSampleMapper.deleteById(faceSample.getId());
} else {
log.info("当前景区{},人脸样本ID{},删除失败", scenicId, faceSample.getId());
}
});
ListFaceEntitiesRequest listFaceEntitiesRequest = new ListFaceEntitiesRequest();
listFaceEntitiesRequest.setDbName(String.valueOf(scenicId));
listFaceEntitiesRequest.setOrder("asc");
try {
IAcsClient client = getClient();
while (true) {
AtomicBoolean flag = new AtomicBoolean(false);
ListFaceEntitiesResponse listFaceEntitiesResponse = client.getAcsResponse(listFaceEntitiesRequest);
if (listFaceEntitiesResponse == null || listFaceEntitiesResponse.getData() == null || listFaceEntitiesResponse.getData().getEntities() == null || listFaceEntitiesResponse.getData().getEntities().isEmpty()) {
break;
}
listFaceEntitiesResponse.getData().getEntities().forEach(entity -> {
String entityId = entity.getEntityId();
String[] split = entityId.split("_");
if (split.length != 2) {
return;
}
String deviceId = split[0];
if (StringUtils.isBlank(deviceId)) {
return;
}
String dateString = split[1];
if (StringUtils.isBlank(dateString)) {
return;
}
if (DateUtils.parse(dateString, DATE_FORMAT).before(endDate)) {
flag.set(true);
log.info("当前景区{},开始删除人脸样本:{}", scenicId, entity.getEntityId());
deleteFaceSample(String.valueOf(scenicId), entity.getEntityId());
} else {
log.info("当前景区{},人脸样本:{}未过期", scenicId, entity.getEntityId());
}
});
if (!flag.get()) {
break;
}
}
} catch (Exception ignored) {
}
}
@Override
@ -321,7 +361,7 @@ public class TaskFaceServiceImpl implements TaskFaceService {
deleteFaceEntityRequest.setDbName(entity.getDbName());
deleteFaceEntityRequest.setEntityId(entity.getEntityId());
try {
deleteEntityLimiter.aquire();
deleteEntityLimiter.acquire();
} catch (InterruptedException ignored) {
}
try {
@ -334,7 +374,7 @@ public class TaskFaceServiceImpl implements TaskFaceService {
DeleteFaceDbRequest deleteFaceDbRequest = new DeleteFaceDbRequest();
deleteFaceDbRequest.setName(dbName);
try {
deleteDbLimiter.aquire();
deleteDbLimiter.acquire();
} catch (InterruptedException ignored) {
}
client.getAcsResponse(deleteFaceDbRequest);
@ -426,10 +466,12 @@ public class TaskFaceServiceImpl implements TaskFaceService {
deleteFaceEntityRequest.setDbName(dbName);
deleteFaceEntityRequest.setEntityId(entityId);
try {
deleteEntityLimiter.acquire();
log.info("删除{}人脸实体:{}", dbName, entityId);
IAcsClient client = getClient();
client.getAcsResponse(deleteFaceEntityRequest);
return true;
} catch (ClientException e) {
} catch (Exception e) {
log.error("删除人脸样本失败!", e);
return false;
}

View File

@ -16,7 +16,6 @@ import com.ycwl.basic.mapper.TaskMapper;
import com.ycwl.basic.mapper.TemplateMapper;
import com.ycwl.basic.mapper.VideoMapper;
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
import com.ycwl.basic.model.mobile.order.PriceObj;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
@ -26,11 +25,9 @@ import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.scenic.entity.ScenicEntity;
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
import com.ycwl.basic.model.pc.source.resp.SourceRespVO;
import com.ycwl.basic.model.pc.task.entity.TaskEntity;
import com.ycwl.basic.model.pc.task.req.TaskReqQuery;
import com.ycwl.basic.model.pc.task.resp.TaskRespVO;
import com.ycwl.basic.model.pc.template.entity.TemplateConfigEntity;
import com.ycwl.basic.model.pc.template.resp.TemplateRespVO;
import com.ycwl.basic.model.pc.video.entity.MemberVideoEntity;
import com.ycwl.basic.model.pc.video.entity.VideoEntity;
@ -69,7 +66,6 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
@ -161,6 +157,9 @@ public class TaskTaskServiceImpl implements TaskService {
req.getTemplateList().forEach(template -> {
if (StringUtils.isNumeric(template.getId())) {
TemplateRespVO dbTemplate = templateRepository.getTemplate(Long.parseLong(template.getId()));
if (dbTemplate == null) {
return;
}
if (!dbTemplate.getUpdateTime().equals(template.getUpdateTime())) {
updTemplateList.add(dbTemplate);
}
@ -171,13 +170,17 @@ public class TaskTaskServiceImpl implements TaskService {
}
try {
if (lock.tryLock(2, TimeUnit.SECONDS)) {
List<TaskRespVO> taskList = taskMapper.selectNotRunning();
resp.setTasks(taskList);
resp.setTemplates(updTemplateList);
taskList.forEach(task -> {
taskMapper.assignToWorker(task.getId(), worker.getId());
videoTaskRepository.clearTaskCache(task.getId());
});
try {
List<TaskRespVO> taskList = taskMapper.selectNotRunning();
resp.setTasks(taskList);
resp.setTemplates(updTemplateList);
taskList.forEach(task -> {
taskMapper.assignToWorker(task.getId(), worker.getId());
videoTaskRepository.clearTaskCache(task.getId());
});
} finally {
lock.unlock();
}
}
} catch (InterruptedException ignored) {
}
@ -214,6 +217,113 @@ public class TaskTaskServiceImpl implements TaskService {
videoTaskRepository.clearTaskCache(taskUpdate.getId());
}
@Override
public void forceCreateTaskByFaceIdAndTempalteId(Long faceId, Long templateId) {
FaceEntity face = faceRepository.getFace(faceId);
if (face == null) {
log.info("faceId:{} is not exist", faceId);
return;
}
List<FaceSampleEntity> faceSampleList = faceRepository.getFaceSampleList(faceId);
if (faceSampleList.isEmpty()) {
log.info("faceId:{} sample list not exist", faceId);
}
List<Long> faceSampleIds = faceSampleList.stream().map(FaceSampleEntity::getId).collect(Collectors.toList());
List<SourceEntity> sourceList = sourceMapper.listVideoByScenicFaceRelation(face.getScenicId(), faceId);
VideoPieceGetter.Task task = new VideoPieceGetter.Task();
task.faceId = faceId;
task.faceSampleIds = faceSampleIds;
task.templateId = templateId;
task.memberId = face.getMemberId();
task.callback = () -> {
log.info("task callback");
List<SourceEntity> videoSourceList = sourceMapper.listVideoByScenicFaceRelation(face.getScenicId(), faceId);
Map<String, List<SourceEntity>> sourcesMap = videoSourceList.stream()
.peek(item -> item.setUrl(item.getVideoUrl()))
.collect(Collectors.groupingBy(item -> item.getDeviceId().toString()));
if (sourcesMap.isEmpty()) {
// 主动禁止没有视频源视频生成
log.info("task callback: 没有视频源");
return;
}
sourcesMap.forEach((key, value) -> {
// 每个value只保留第一个
value.removeIf(item -> !value.get(0).equals(item));
});
TaskReqQuery taskReqQuery = new TaskReqQuery();
taskReqQuery.setFaceId(faceId);
taskReqQuery.setTemplateId(templateId);
taskReqQuery.setTaskParams(JSON.toJSONString(sourcesMap));
List<TaskRespVO> list = taskMapper.list(taskReqQuery);
MemberVideoEntity memberVideoEntity = new MemberVideoEntity();
memberVideoEntity.setMemberId(face.getMemberId());
memberVideoEntity.setScenicId(face.getScenicId());
memberVideoEntity.setFaceId(faceId);
memberVideoEntity.setTemplateId(templateId);
memberVideoEntity.setIsBuy(0);
if (list.isEmpty()) {
log.info("创建任务! faceId:{},templateId:{},taskParams:{}", faceId, templateId, sourcesMap);
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(face.getScenicId());
TaskEntity taskEntity = null;
if (Integer.valueOf(0).equals(scenicConfig.getTemplateNewVideoType())) {
log.info("景区{}启用:templateNewVideoType:全新视频原位替换", face.getScenicId());
taskReqQuery.setTemplateId(templateId);
List<TaskEntity> templateTaskList = taskMapper.listEntity(taskReqQuery);
if (!templateTaskList.isEmpty()) {
taskEntity = templateTaskList.get(0);
log.info("已有旧生成的视频:{}", taskEntity);
MemberVideoEntity taskVideoRelation = videoMapper.queryRelationByMemberTask(face.getMemberId(), taskEntity.getId());
if (taskVideoRelation != null) {
log.info("已有旧关联记录的视频:{}", taskVideoRelation);
memberVideoEntity.setIsBuy(taskVideoRelation.getIsBuy());
memberVideoEntity.setOrderId(taskVideoRelation.getOrderId());
}
taskMapper.deleteById(taskEntity.getId());
}
}
if (taskEntity == null) {
taskEntity = new TaskEntity();
taskEntity.setId(SnowFlakeUtil.getLongId());
taskEntity.setScenicId(face.getScenicId());
taskEntity.setFaceId(faceId);
taskEntity.setTemplateId(templateId);
taskEntity.setAutomatic(0);
}
taskEntity.setWorkerId(null);
taskEntity.setStatus(0);
taskEntity.setTaskParams(JSON.toJSONString(sourcesMap));
taskMapper.add(taskEntity);
memberVideoEntity.setTaskId(taskEntity.getId());
} else {
log.info("重复task! faceId:{},templateId:{},taskParams:{}", faceId, templateId, sourcesMap);
memberVideoEntity.setTaskId(list.get(0).getId());
VideoEntity video = videoMapper.findByTaskId(list.get(0).getId());
if (video != null) {
IsBuyRespVO isBuy = orderBiz.isBuy(face.getMemberId(), list.get(0).getScenicId(), 0, video.getId());
if (isBuy.isBuy()) {
memberVideoEntity.setIsBuy(1);
memberVideoEntity.setOrderId(isBuy.getOrderId());
}
if (isBuy.isFree()) {
memberVideoEntity.setIsBuy(1);
}
memberVideoEntity.setVideoId(video.getId());
}
}
videoMapper.addRelation(memberVideoEntity);
};
if (faceSampleIds.isEmpty()) {
// 没有人脸样本
if (!sourceList.isEmpty()) {
// 但是有原片
task.callback.onInvoke();
}
} else {
VideoPieceGetter.addTask(task);
}
}
@Override
public void autoCreateTaskByFaceId(Long faceId) {
FaceRespVO faceRespVO = faceMapper.getById(faceId);
@ -410,6 +520,7 @@ public class TaskTaskServiceImpl implements TaskService {
taskUpdate.setWorkerId(worker.getId());
taskMapper.setSuccess(taskUpdate);
videoTaskRepository.clearTaskCache(taskUpdate.getId());
VideoEntity video = videoMapper.findByTaskId(taskId);
if (video != null) {
video.setVideoUrl(task.getVideoUrl());
@ -503,7 +614,7 @@ public class TaskTaskServiceImpl implements TaskService {
taskMapper.update(updateTask);
videoTaskRepository.clearTaskCache(updateTask.getId());
}
return adapter.getUrlForUpload(filename);
return adapter.getUrlForUpload(new Date(System.currentTimeMillis() + 1000 * 60 * 60), "video/mp4", filename);
}
public void sendVideoGeneratedServiceNotification(Long taskId) {