避免重复创建

This commit is contained in:
Jerry Yan 2025-04-07 09:46:16 +08:00
parent 389c28300f
commit 84287df87b
10 changed files with 128 additions and 221 deletions

View File

@ -38,6 +38,7 @@ import com.ycwl.basic.model.viid.resp.SystemTimeResp;
import com.ycwl.basic.model.viid.resp.VIIDBaseResp; import com.ycwl.basic.model.viid.resp.VIIDBaseResp;
import com.ycwl.basic.repository.DeviceRepository; import com.ycwl.basic.repository.DeviceRepository;
import com.ycwl.basic.repository.ScenicRepository; import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.service.task.TaskFaceService; import com.ycwl.basic.service.task.TaskFaceService;
import com.ycwl.basic.storage.StorageFactory; import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter; import com.ycwl.basic.storage.adapters.IStorageAdapter;
@ -93,6 +94,8 @@ public class ViidController {
@Autowired @Autowired
private TaskFaceService taskFaceService; private TaskFaceService taskFaceService;
private final Map<String, ThreadPoolExecutor> executors = new ConcurrentHashMap<>(); private final Map<String, ThreadPoolExecutor> executors = new ConcurrentHashMap<>();
@Autowired
private ScenicService scenicService;
private ThreadPoolExecutor getExecutor(String deviceId) { private ThreadPoolExecutor getExecutor(String deviceId) {
ThreadPoolExecutor executor = executors.get(deviceId); ThreadPoolExecutor executor = executors.get(deviceId);
@ -273,21 +276,8 @@ public class ViidController {
if (scenicId == null) { if (scenicId == null) {
continue; continue;
} }
IStorageAdapter scenicStorageAdapter; IStorageAdapter scenicStorageAdapter = scenicService.getScenicStorageAdapter(scenicId);
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId); IFaceBodyAdapter faceBodyAdapter = scenicService.getScenicFaceBodyAdapter(scenicId);
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
scenicStorageAdapter = StorageFactory.get(scenicConfig.getStoreType());
scenicStorageAdapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
} else {
scenicStorageAdapter = StorageFactory.use("video");
}
IFaceBodyAdapter faceBodyAdapter;
if (scenicConfig != null && scenicConfig.getFaceType() != null) {
faceBodyAdapter = FaceBodyFactory.getAdapter(scenicConfig.getFaceType());
faceBodyAdapter.loadConfig(JSONObject.parseObject(scenicConfig.getFaceConfigJson(), Map.class));
} else {
faceBodyAdapter = null;
}
FacePositionObject facePosition = new FacePositionObject(); FacePositionObject facePosition = new FacePositionObject();
facePosition.setLtY(face.getLeftTopY()); facePosition.setLtY(face.getLeftTopY());
facePosition.setLtX(face.getLeftTopX()); facePosition.setLtX(face.getLeftTopX());

View File

@ -7,9 +7,11 @@ import com.ycwl.basic.constant.StorageConstant;
import com.ycwl.basic.device.entity.common.FileObject; import com.ycwl.basic.device.entity.common.FileObject;
import com.ycwl.basic.device.operator.VptPassiveStorageOperator; import com.ycwl.basic.device.operator.VptPassiveStorageOperator;
import com.ycwl.basic.device.operator.VptPassiveStorageOperator; import com.ycwl.basic.device.operator.VptPassiveStorageOperator;
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity; import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.wvp.WvpSyncReqVo; import com.ycwl.basic.model.wvp.WvpSyncReqVo;
import com.ycwl.basic.repository.ScenicRepository; import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.storage.StorageFactory; import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter; import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.storage.enums.StorageAcl; import com.ycwl.basic.storage.enums.StorageAcl;
@ -18,6 +20,7 @@ import com.ycwl.basic.utils.ApiResponse;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
@ -35,11 +38,8 @@ import java.util.Map;
@RequestMapping("/vpt/v1/") @RequestMapping("/vpt/v1/")
public class VptController { public class VptController {
private final ScenicRepository scenicRepository; @Autowired
private ScenicService scenicService;
public VptController(ScenicRepository scenicRepository) {
this.scenicRepository = scenicRepository;
}
@IgnoreLogReq @IgnoreLogReq
@PostMapping("/scenic/{scenicId}/sync") @PostMapping("/scenic/{scenicId}/sync")
@ -48,14 +48,7 @@ public class VptController {
} }
@PostMapping("/scenic/{scenicId}/{taskId}/uploadUrl") @PostMapping("/scenic/{scenicId}/{taskId}/uploadUrl")
public String uploadUrl(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) { public String uploadUrl(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) {
IStorageAdapter adapter; IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
adapter = StorageFactory.get(scenicConfig.getStoreType());
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
} else {
adapter = StorageFactory.use("video");
}
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4"); String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
String urlForUpload = adapter.getUrlForUpload(new Date(System.currentTimeMillis() + 1000 * 60 * 60), "video/mp4", filename); String urlForUpload = adapter.getUrlForUpload(new Date(System.currentTimeMillis() + 1000 * 60 * 60), "video/mp4", filename);
urlForUpload = urlForUpload.replace("-internal.aliyuncs.com", ".aliyuncs.com"); urlForUpload = urlForUpload.replace("-internal.aliyuncs.com", ".aliyuncs.com");
@ -63,14 +56,7 @@ public class VptController {
} }
@PostMapping("/scenic/{scenicId}/{taskId}/success") @PostMapping("/scenic/{scenicId}/{taskId}/success")
public ApiResponse<String> success(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId, @RequestBody FileObject fileObject) { public ApiResponse<String> success(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId, @RequestBody FileObject fileObject) {
IStorageAdapter adapter; IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
adapter = StorageFactory.get(scenicConfig.getStoreType());
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
} else {
adapter = StorageFactory.use("video");
}
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4"); String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
fileObject.setUrl(adapter.getUrl(filename)); fileObject.setUrl(adapter.getUrl(filename));
adapter.setAcl(StorageAcl.PUBLIC_READ, filename); adapter.setAcl(StorageAcl.PUBLIC_READ, filename);

View File

@ -10,6 +10,7 @@ import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.wvp.WvpSyncReqVo; import com.ycwl.basic.model.wvp.WvpSyncReqVo;
import com.ycwl.basic.repository.ScenicRepository; import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.pc.DeviceService; import com.ycwl.basic.service.pc.DeviceService;
import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.storage.StorageFactory; import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter; import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.storage.enums.StorageAcl; import com.ycwl.basic.storage.enums.StorageAcl;
@ -39,7 +40,7 @@ public class WvpController {
@Autowired @Autowired
private DeviceService deviceService; private DeviceService deviceService;
@Autowired @Autowired
private ScenicRepository scenicRepository; private ScenicService scenicService;
@IgnoreLogReq @IgnoreLogReq
@PostMapping("/scenic/{scenicId}/sync") @PostMapping("/scenic/{scenicId}/sync")
@ -50,14 +51,7 @@ public class WvpController {
@PostMapping("/scenic/{scenicId}/{taskId}/uploadUrl") @PostMapping("/scenic/{scenicId}/{taskId}/uploadUrl")
public String uploadUrl(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) { public String uploadUrl(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) {
IStorageAdapter adapter; IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
adapter = StorageFactory.get(scenicConfig.getStoreType());
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
} else {
adapter = StorageFactory.use("video");
}
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4"); String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
String urlForUpload = adapter.getUrlForUpload(new Date(System.currentTimeMillis() + 1000 * 60 * 60), "video/mp4", filename); String urlForUpload = adapter.getUrlForUpload(new Date(System.currentTimeMillis() + 1000 * 60 * 60), "video/mp4", filename);
urlForUpload = urlForUpload.replace("-internal.aliyuncs.com", ".aliyuncs.com"); urlForUpload = urlForUpload.replace("-internal.aliyuncs.com", ".aliyuncs.com");
@ -65,14 +59,7 @@ public class WvpController {
} }
@PostMapping("/scenic/{scenicId}/{taskId}/success") @PostMapping("/scenic/{scenicId}/{taskId}/success")
public ApiResponse<String> success(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId, @RequestBody FileObject fileObject) { public ApiResponse<String> success(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId, @RequestBody FileObject fileObject) {
IStorageAdapter adapter; IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
adapter = StorageFactory.get(scenicConfig.getStoreType());
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
} else {
adapter = StorageFactory.use("video");
}
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4"); String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
fileObject.setUrl(adapter.getUrl(filename)); fileObject.setUrl(adapter.getUrl(filename));
adapter.setAcl(StorageAcl.PUBLIC_READ, filename); adapter.setAcl(StorageAcl.PUBLIC_READ, filename);

View File

@ -1,10 +1,12 @@
package com.ycwl.basic.service.pc; package com.ycwl.basic.service.pc;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity; import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq; import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery; import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO; import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.utils.ApiResponse; import com.ycwl.basic.utils.ApiResponse;
import java.util.List; import java.util.List;
@ -31,4 +33,8 @@ public interface ScenicService {
ScenicConfigEntity getConfig(Long id); ScenicConfigEntity getConfig(Long id);
void saveConfig(Long configId, ScenicConfigEntity config); void saveConfig(Long configId, ScenicConfigEntity config);
IStorageAdapter getScenicStorageAdapter(Long scenicId);
IFaceBodyAdapter getScenicFaceBodyAdapter(Long scenicId);
} }

View File

@ -28,6 +28,7 @@ import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
import com.ycwl.basic.repository.FaceRepository; import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.repository.ScenicRepository; import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.pc.FaceService; import com.ycwl.basic.service.pc.FaceService;
import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.service.task.TaskFaceService; import com.ycwl.basic.service.task.TaskFaceService;
import com.ycwl.basic.service.task.TaskService; import com.ycwl.basic.service.task.TaskService;
import com.ycwl.basic.storage.StorageFactory; import com.ycwl.basic.storage.StorageFactory;
@ -75,6 +76,8 @@ public class FaceServiceImpl implements FaceService {
private VideoMapper videoMapper; private VideoMapper videoMapper;
@Autowired @Autowired
private ScenicRepository scenicRepository; private ScenicRepository scenicRepository;
@Autowired
private ScenicService scenicService;
@Override @Override
public ApiResponse<PageInfo<FaceRespVO>> pageQuery(FaceReqQuery faceReqQuery) { public ApiResponse<PageInfo<FaceRespVO>> pageQuery(FaceReqQuery faceReqQuery) {
@ -303,7 +306,8 @@ public class FaceServiceImpl implements FaceService {
new Thread(() -> { new Thread(() -> {
sourceMapper.deleteNotBuyFaceRelation(face.getMemberId(), faceId); sourceMapper.deleteNotBuyFaceRelation(face.getMemberId(), faceId);
videoMapper.deleteNotBuyFaceRelations(face.getMemberId(), faceId); videoMapper.deleteNotBuyFaceRelations(face.getMemberId(), faceId);
faceService.deleteFaceSample(face.getScenicId(), USER_FACE_DB_NAME+face.getScenicId().toString(), faceId.toString()); IFaceBodyAdapter adapter = scenicService.getScenicFaceBodyAdapter(face.getScenicId());
adapter.deleteFace(USER_FACE_DB_NAME+face.getScenicId().toString(), faceId.toString());
}).start(); }).start();
return ApiResponse.success("删除成功"); return ApiResponse.success("删除成功");
} }

View File

@ -15,6 +15,8 @@ import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
import com.ycwl.basic.repository.ScenicRepository; import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.pc.ScenicService; import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.service.task.TaskFaceService; import com.ycwl.basic.service.task.TaskFaceService;
import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.utils.ApiResponse; import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.utils.SnowFlakeUtil; import com.ycwl.basic.utils.SnowFlakeUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -25,6 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME; import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME;
@ -93,17 +96,15 @@ public class ScenicServiceImpl implements ScenicService {
int i = scenicMapper.deleteById(id); int i = scenicMapper.deleteById(id);
if (i > 0) { if (i > 0) {
scenicAccountMapper.deleteByScenicId(id); scenicAccountMapper.deleteByScenicId(id);
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(id); IFaceBodyAdapter adapter = getScenicFaceBodyAdapter(id);
if (scenicConfig != null && scenicConfig.getFaceType() != null) { (new Thread(() -> {
IFaceBodyAdapter adapter = FaceBodyFactory.getAdapter(scenicConfig.getFaceType()); adapter.deleteFaceDb(id.toString());
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getFaceConfigJson(), Map.class)); adapter.deleteFaceDb(USER_FACE_DB_NAME + id);
(new Thread(() -> { })).start();
adapter.deleteFaceDb(id.toString());
adapter.deleteFaceDb(USER_FACE_DB_NAME + id);
})).start();
}
scenicMapper.deleteConfigByScenicId(id); scenicMapper.deleteConfigByScenicId(id);
scenicRepository.clearCache(id); scenicRepository.clearCache(id);
scenicFaceBodyAdapterMap.remove(id);
scenicStorageAdapterMap.remove(id);
return ApiResponse.success(true); return ApiResponse.success(true);
}else { }else {
return ApiResponse.fail("景区删除失败"); return ApiResponse.fail("景区删除失败");
@ -194,5 +195,39 @@ public class ScenicServiceImpl implements ScenicService {
} }
scenicMapper.updateConfigById(config); scenicMapper.updateConfigById(config);
scenicRepository.clearCache(config.getScenicId()); scenicRepository.clearCache(config.getScenicId());
scenicFaceBodyAdapterMap.remove(config.getScenicId());
scenicStorageAdapterMap.remove(config.getScenicId());
}
private static final Map<Long, IStorageAdapter> scenicStorageAdapterMap = new ConcurrentHashMap<>();
@Override
public IStorageAdapter getScenicStorageAdapter(Long scenicId) {
return scenicStorageAdapterMap.computeIfAbsent(scenicId, (key) -> {
IStorageAdapter adapter;
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
adapter = StorageFactory.get(scenicConfig.getStoreType());
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
} else {
adapter = StorageFactory.use("video");
}
return adapter;
});
}
private static final Map<Long, IFaceBodyAdapter> scenicFaceBodyAdapterMap = new ConcurrentHashMap<>();
@Override
public IFaceBodyAdapter getScenicFaceBodyAdapter(Long scenicId) {
return scenicFaceBodyAdapterMap.computeIfAbsent(scenicId, (key) -> {
IFaceBodyAdapter adapter;
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
if (scenicConfig != null && scenicConfig.getFaceType() != null) {
adapter = FaceBodyFactory.getAdapter(scenicConfig.getFaceType());
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getFaceConfigJson(), Map.class));
} else {
adapter = FaceBodyFactory.use();
}
return adapter;
});
} }
} }

View File

@ -10,8 +10,6 @@ public interface TaskFaceService {
SearchFaceRespVo searchFace(IFaceBodyAdapter adapter, String dbName, String faceUrl, String reason); SearchFaceRespVo searchFace(IFaceBodyAdapter adapter, String dbName, String faceUrl, String reason);
void batchDeleteExpiredFace(Long scenicId);
String uploadFile(MultipartFile file, Long userId); String uploadFile(MultipartFile file, Long userId);
boolean deleteFaceSample(Long scenicId, String dbName, String entityId); boolean deleteFaceSample(Long scenicId, String dbName, String entityId);

View File

@ -35,6 +35,7 @@ import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
import com.ycwl.basic.repository.DeviceRepository; import com.ycwl.basic.repository.DeviceRepository;
import com.ycwl.basic.repository.FaceRepository; import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.repository.ScenicRepository; import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.service.task.TaskFaceService; import com.ycwl.basic.service.task.TaskFaceService;
import com.ycwl.basic.storage.StorageFactory; import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter; import com.ycwl.basic.storage.adapters.IStorageAdapter;
@ -46,6 +47,7 @@ import com.ycwl.basic.utils.ratelimiter.IRateLimiter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.aliyuncs.IAcsClient; import com.aliyuncs.IAcsClient;
@ -77,8 +79,6 @@ public class TaskFaceServiceImpl implements TaskFaceService {
@Autowired @Autowired
private FaceSampleMapper faceSampleMapper; private FaceSampleMapper faceSampleMapper;
@Autowired @Autowired
private ScenicMapper scenicMapper;
@Autowired
private RedisTemplate<String, String> redisTemplate; private RedisTemplate<String, String> redisTemplate;
@Autowired @Autowired
private FaceDetectLogMapper logMapper; private FaceDetectLogMapper logMapper;
@ -93,6 +93,9 @@ public class TaskFaceServiceImpl implements TaskFaceService {
private ScenicRepository scenicRepository; private ScenicRepository scenicRepository;
@Autowired @Autowired
private DeviceRepository deviceRepository; private DeviceRepository deviceRepository;
@Autowired
@Lazy
private ScenicService scenicService;
private IAcsClient getClient() { private IAcsClient getClient() {
AliFaceBodyAdapter use = (AliFaceBodyAdapter) FaceBodyFactory.use(); AliFaceBodyAdapter use = (AliFaceBodyAdapter) FaceBodyFactory.use();
@ -295,118 +298,6 @@ public class TaskFaceServiceImpl implements TaskFaceService {
} }
} }
@Override
public void batchDeleteExpiredFace(Long scenicId) {
log.info("当前景区{},开始删除人脸样本", scenicId);
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
Integer sampleStoreDay = scenicConfig.getSampleStoreDay();
if (sampleStoreDay == null) {
log.info("当前景区{}人脸样本保存天数未设置默认7天", scenicId);
sampleStoreDay = 7;
}
Date endDate = DateUtil.offsetDay(DateUtil.beginOfDay(new Date()), -sampleStoreDay);
ListFaceEntitiesRequest listFaceEntitiesRequest = new ListFaceEntitiesRequest();
AtomicInteger count = new AtomicInteger(0);
IAcsClient client = getClient();
FixedRateLimiter limiter = new FixedRateLimiter(2);
listFaceEntitiesRequest.setDbName(USER_FACE_DB_NAME + String.valueOf(scenicId));
listFaceEntitiesRequest.setToken(null);
listFaceEntitiesRequest.setEntityIdPrefix("");
count.set(0);
while (true) {
try {
listFaceEntitiesRequest.setOffset(count.get());
try {
limiter.acquire();
} catch (InterruptedException ignored) {
}
ListFaceEntitiesResponse listFaceEntitiesResponse = client.getAcsResponse(listFaceEntitiesRequest);
if (listFaceEntitiesResponse == null || listFaceEntitiesResponse.getData() == null || listFaceEntitiesResponse.getData().getEntities() == null || listFaceEntitiesResponse.getData().getEntities().isEmpty()) {
break;
}
listFaceEntitiesRequest.setToken(listFaceEntitiesResponse.getData().getToken());
listFaceEntitiesResponse.getData().getEntities().forEach(entity -> {
String entityId = entity.getEntityId();
String[] split = entityId.split("_");
if (split.length != 2) {
return;
}
String dateString = split[1];
if (StringUtils.isBlank(dateString)) {
return;
}
if (DateUtils.parse(dateString, DATE_FORMAT).before(endDate)) {
deleteFaceSample(scenicId, entity.getDbName(), entity.getEntityId());
} else {
count.incrementAndGet();
log.info("当前景区{},人脸样本:{}未过期", scenicId, entity.getEntityId());
}
});
} catch (Exception e) {
log.error("当前景区{},删除人脸样本失败", scenicId, e);
}
}
List<DeviceEntity> devices = deviceRepository.getAllDeviceByScenicId(scenicId);
listFaceEntitiesRequest.setDbName(String.valueOf(scenicId));
listFaceEntitiesRequest.setToken(null);
listFaceEntitiesRequest.setOrder("asc");
devices.forEach(device -> {
count.set(0);
listFaceEntitiesRequest.setEntityIdPrefix(device.getId() + "_");
try {
while (true) {
listFaceEntitiesRequest.setOffset(count.get());
try {
limiter.acquire();
} catch (InterruptedException ignored) {
}
ListFaceEntitiesResponse listFaceEntitiesResponse = client.getAcsResponse(listFaceEntitiesRequest);
if (listFaceEntitiesResponse == null || listFaceEntitiesResponse.getData() == null || listFaceEntitiesResponse.getData().getEntities() == null || listFaceEntitiesResponse.getData().getEntities().isEmpty()) {
break;
}
listFaceEntitiesRequest.setToken(listFaceEntitiesResponse.getData().getToken());
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)) {
deleteFaceSample(scenicId, entity.getDbName(), entity.getEntityId());
} else {
count.incrementAndGet();
log.info("当前景区{},人脸样本:{}未过期", scenicId, entity.getEntityId());
}
});
}
} catch (Exception ignored) {
}
});
List<FaceSampleEntity> faceSampleList = faceSampleMapper.listEntityBeforeDate(scenicId, endDate);
if (faceSampleList.isEmpty()) {
log.info("当前景区{},人脸样本为空", scenicId);
return;
}
faceSampleList.forEach(faceSample -> {
boolean success = deleteFaceSample(scenicId, String.valueOf(scenicId), generateEntityId(faceSample));
if (success) {
log.info("当前景区{}人脸样本ID{},删除成功", scenicId, faceSample.getId());
faceSampleMapper.deleteById(faceSample.getId());
} else {
log.info("当前景区{}人脸样本ID{},删除失败", scenicId, faceSample.getId());
}
});
}
@Override @Override
public String uploadFile(MultipartFile file, Long userId) { public String uploadFile(MultipartFile file, Long userId) {
if (file.isEmpty()) { if (file.isEmpty()) {
@ -434,16 +325,10 @@ public class TaskFaceServiceImpl implements TaskFaceService {
@Override @Override
public boolean deleteFaceSample(Long scenicId, String dbName, String entityId) { public boolean deleteFaceSample(Long scenicId, String dbName, String entityId) {
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId); ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
IFaceBodyAdapter faceBodyAdapter; IFaceBodyAdapter adapter = scenicService.getScenicFaceBodyAdapter(scenicId);
if (scenicConfig != null && scenicConfig.getFaceType() != null) {
faceBodyAdapter = FaceBodyFactory.getAdapter(scenicConfig.getFaceType());
faceBodyAdapter.loadConfig(JSONObject.parseObject(scenicConfig.getFaceConfigJson(), Map.class));
} else {
faceBodyAdapter = FaceBodyFactory.use();
}
log.info("删除{}人脸实体:{}", dbName, entityId); log.info("删除{}人脸实体:{}", dbName, entityId);
try { try {
faceBodyAdapter.deleteFace(dbName, entityId); adapter.deleteFace(dbName, entityId);
return true; return true;
} catch (Exception e) { } catch (Exception e) {
log.error("删除人脸样本失败!", e); log.error("删除人脸样本失败!", e);

View File

@ -49,6 +49,7 @@ import com.ycwl.basic.repository.OrderRepository;
import com.ycwl.basic.repository.ScenicRepository; import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.repository.VideoRepository; import com.ycwl.basic.repository.VideoRepository;
import com.ycwl.basic.repository.VideoTaskRepository; import com.ycwl.basic.repository.VideoTaskRepository;
import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.service.task.TaskService; import com.ycwl.basic.service.task.TaskService;
import com.ycwl.basic.storage.StorageFactory; import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter; import com.ycwl.basic.storage.adapters.IStorageAdapter;
@ -117,6 +118,9 @@ public class TaskTaskServiceImpl implements TaskService {
private VideoRepository videoRepository; private VideoRepository videoRepository;
@Autowired @Autowired
private OrderRepository orderRepository; private OrderRepository orderRepository;
@Autowired
private ScenicService scenicService;
private final ReentrantLock lock = new ReentrantLock(); private final ReentrantLock lock = new ReentrantLock();
@Autowired @Autowired
private TaskStatusBiz taskStatusBiz; private TaskStatusBiz taskStatusBiz;
@ -585,14 +589,8 @@ public class TaskTaskServiceImpl implements TaskService {
} }
videoMapper.add(video); videoMapper.add(video);
} }
IStorageAdapter adapter;
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(task.getScenicId()); ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(task.getScenicId());
if (scenicConfig != null && scenicConfig.getStoreType() != null) { IStorageAdapter adapter = scenicService.getScenicStorageAdapter(task.getScenicId());
adapter = StorageFactory.get(scenicConfig.getStoreType());
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
} else {
adapter = StorageFactory.use("video");
}
String filename = StorageUtil.joinPath(StorageConstant.VLOG_PATH, task.getId() + "_" + task.getScenicId() + ".mp4"); String filename = StorageUtil.joinPath(StorageConstant.VLOG_PATH, task.getId() + "_" + task.getScenicId() + ".mp4");
adapter.setAcl(StorageAcl.PUBLIC_READ, filename); adapter.setAcl(StorageAcl.PUBLIC_READ, filename);
int isBuy = 0; int isBuy = 0;
@ -651,14 +649,7 @@ public class TaskTaskServiceImpl implements TaskService {
if (task == null) { if (task == null) {
return null; return null;
} }
IStorageAdapter adapter; IStorageAdapter adapter = scenicService.getScenicStorageAdapter(task.getScenicId());
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(task.getScenicId());
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
adapter = StorageFactory.get(scenicConfig.getStoreType());
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
} else {
adapter = StorageFactory.use("video");
}
String filename = StorageUtil.joinPath(StorageConstant.VLOG_PATH, task.getId() + "_" + task.getScenicId() + ".mp4"); String filename = StorageUtil.joinPath(StorageConstant.VLOG_PATH, task.getId() + "_" + task.getScenicId() + ".mp4");
if (StringUtils.isBlank(task.getVideoUrl())) { if (StringUtils.isBlank(task.getVideoUrl())) {
// 生成 // 生成

View File

@ -3,6 +3,7 @@ package com.ycwl.basic.task;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.ycwl.basic.constant.StorageConstant; import com.ycwl.basic.constant.StorageConstant;
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
import com.ycwl.basic.mapper.FaceMapper; import com.ycwl.basic.mapper.FaceMapper;
import com.ycwl.basic.mapper.FaceSampleMapper; import com.ycwl.basic.mapper.FaceSampleMapper;
import com.ycwl.basic.mapper.ScenicMapper; import com.ycwl.basic.mapper.ScenicMapper;
@ -10,6 +11,7 @@ import com.ycwl.basic.mapper.SourceMapper;
import com.ycwl.basic.mapper.VideoMapper; import com.ycwl.basic.mapper.VideoMapper;
import com.ycwl.basic.model.pc.face.req.FaceReqQuery; import com.ycwl.basic.model.pc.face.req.FaceReqQuery;
import com.ycwl.basic.model.pc.face.resp.FaceRespVO; import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
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.req.FaceSampleReqQuery;
import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO; 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.entity.ScenicConfigEntity;
@ -20,6 +22,7 @@ import com.ycwl.basic.model.pc.source.resp.SourceRespVO;
import com.ycwl.basic.model.pc.video.req.VideoReqQuery; import com.ycwl.basic.model.pc.video.req.VideoReqQuery;
import com.ycwl.basic.model.pc.video.resp.VideoRespVO; import com.ycwl.basic.model.pc.video.resp.VideoRespVO;
import com.ycwl.basic.repository.ScenicRepository; import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.service.task.TaskFaceService; import com.ycwl.basic.service.task.TaskFaceService;
import com.ycwl.basic.storage.StorageFactory; import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter; import com.ycwl.basic.storage.adapters.IStorageAdapter;
@ -37,6 +40,7 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME; import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME;
import static com.ycwl.basic.service.task.impl.TaskFaceServiceImpl.generateEntityId;
@Component @Component
@EnableScheduling @EnableScheduling
@ -46,8 +50,6 @@ public class FaceCleaner {
@Autowired @Autowired
private ScenicMapper scenicMapper; private ScenicMapper scenicMapper;
@Autowired @Autowired
private TaskFaceService faceService;
@Autowired
private FaceSampleMapper faceSampleMapper; private FaceSampleMapper faceSampleMapper;
@Autowired @Autowired
private SourceMapper sourceMapper; private SourceMapper sourceMapper;
@ -57,39 +59,66 @@ public class FaceCleaner {
private ScenicRepository scenicRepository; private ScenicRepository scenicRepository;
@Autowired @Autowired
private FaceMapper faceMapper; private FaceMapper faceMapper;
@Autowired
private ScenicService scenicService;
@Scheduled(cron = "0 0 4 * * ?") @Scheduled(cron = "0 0 1 * * ?")
public void clean(){ public void clean(){
ScenicReqQuery scenicQuery = new ScenicReqQuery(); ScenicReqQuery scenicQuery = new ScenicReqQuery();
List<ScenicRespVO> scenicList = scenicMapper.list(scenicQuery); List<ScenicRespVO> scenicList = scenicMapper.list(scenicQuery);
scenicList.forEach(scenic -> { scenicList.forEach(scenic -> {
log.info("当前景区{},开始删除人脸样本", scenic.getName()); log.info("当前景区{},开始删除人脸样本", scenic.getId());
faceService.batchDeleteExpiredFace(scenic.getId()); IFaceBodyAdapter adapter = scenicService.getScenicFaceBodyAdapter(scenic.getId());
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenic.getId());
Integer sampleStoreDay = scenicConfig.getSampleStoreDay();
if (sampleStoreDay == null) {
log.info("当前景区{}人脸样本保存天数未设置默认7天", scenic.getId());
sampleStoreDay = 7;
}
Date sampleEndDate = DateUtil.offsetDay(DateUtil.beginOfDay(new Date()), -sampleStoreDay);
List<FaceSampleEntity> faceSampleList = faceSampleMapper.listEntityBeforeDate(scenic.getId(), sampleEndDate);
if (faceSampleList.isEmpty()) {
log.info("当前景区{},人脸样本为空", scenic.getId());
return;
}
faceSampleList.forEach(faceSample -> {
boolean success = adapter.deleteFace(String.valueOf(scenic.getId()), generateEntityId(faceSample));
if (success) {
log.info("当前景区{}人脸样本ID{},删除成功", scenic.getId(), faceSample.getId());
faceSampleMapper.deleteById(faceSample.getId());
} else {
log.info("当前景区{}人脸样本ID{},删除失败", scenic.getId(), faceSample.getId());
}
});
}); });
} }
@Scheduled(cron = "0 0 3 * * ?") @Scheduled(cron = "0 45 2 * * ?")
public void deleteExpireFace() { public void deleteExpireFace() {
ScenicReqQuery scenicQuery = new ScenicReqQuery(); ScenicReqQuery scenicQuery = new ScenicReqQuery();
List<ScenicRespVO> scenicList = scenicMapper.list(scenicQuery); List<ScenicRespVO> scenicList = scenicMapper.list(scenicQuery);
scenicList.parallelStream().forEach(scenic -> { scenicList.parallelStream().forEach(scenic -> {
log.info("当前景区{},开始删除用户人脸", scenic.getId());
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenic.getId()); ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenic.getId());
Integer sampleStoreDay = scenicConfig.getSampleStoreDay(); IFaceBodyAdapter adapter = scenicService.getScenicFaceBodyAdapter(scenic.getId());
if (sampleStoreDay == null) { Integer faceStoreDay = scenicConfig.getFaceStoreDay();
if (faceStoreDay == null) {
log.info("当前景区{}人脸样本保存天数未设置默认3天", scenic.getName()); log.info("当前景区{}人脸样本保存天数未设置默认3天", scenic.getName());
sampleStoreDay = 3; faceStoreDay = 3;
} }
FaceReqQuery req = new FaceReqQuery(); FaceReqQuery req = new FaceReqQuery();
req.setScenicId(scenic.getId()); req.setScenicId(scenic.getId());
req.setUpdateEndTime(DateUtil.offsetDay(DateUtil.beginOfDay(new Date()), -sampleStoreDay)); req.setUpdateEndTime(DateUtil.offsetDay(DateUtil.beginOfDay(new Date()), -faceStoreDay));
List<FaceRespVO> list = faceMapper.list(req); List<FaceRespVO> list = faceMapper.list(req);
list.forEach(face -> { list.forEach(face -> {
boolean result = faceService.deleteFaceSample(face.getScenicId(), USER_FACE_DB_NAME+face.getScenicId(), face.getId().toString()); boolean result = adapter.deleteFace(USER_FACE_DB_NAME+face.getScenicId(), face.getId().toString());
if (result) { if (result) {
log.info("当前景区{}人脸样本ID{},删除成功", scenic.getId(), face.getId());
faceMapper.deleteById(face.getId()); faceMapper.deleteById(face.getId());
} else {
log.info("当前景区{}人脸样本ID{},删除失败", scenic.getId(), face.getId());
} }
}); });
log.info("当前景区{},删除人脸样本{}个", scenic.getName(), list.size());
}); });
} }
@ -174,7 +203,7 @@ public class FaceCleaner {
}); });
} }
@Scheduled(cron = "0 0 5 * * ?") @Scheduled(cron = "0 0 1 * * ?")
public void clearOss(){ public void clearOss(){
cleanFaceSampleOss(); cleanFaceSampleOss();
cleanSourceOss(); cleanSourceOss();
@ -196,9 +225,7 @@ public class FaceCleaner {
log.info("开始清理源视频素材文件"); log.info("开始清理源视频素材文件");
List<SourceRespVO> list = sourceMapper.list(new SourceReqQuery()); List<SourceRespVO> list = sourceMapper.list(new SourceReqQuery());
scenicMapper.list(new ScenicReqQuery()).forEach(scenic -> { scenicMapper.list(new ScenicReqQuery()).forEach(scenic -> {
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenic.getId()); IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenic.getId());
IStorageAdapter adapter = StorageFactory.get(scenicConfig.getStoreType());
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
log.info("开始清理视频文件"); log.info("开始清理视频文件");
List<StorageFileObject> fileObjectList = adapter.listDir(StorageConstant.VIDEO_PIECE_PATH); List<StorageFileObject> fileObjectList = adapter.listDir(StorageConstant.VIDEO_PIECE_PATH);
fileObjectList.parallelStream().forEach(fileObject -> { fileObjectList.parallelStream().forEach(fileObject -> {
@ -225,9 +252,7 @@ public class FaceCleaner {
log.info("开始清理视频文件"); log.info("开始清理视频文件");
List<VideoRespVO> list = videoMapper.list(new VideoReqQuery()); List<VideoRespVO> list = videoMapper.list(new VideoReqQuery());
scenicMapper.list(new ScenicReqQuery()).forEach(scenic -> { scenicMapper.list(new ScenicReqQuery()).forEach(scenic -> {
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenic.getId()); IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenic.getId());
IStorageAdapter adapter = StorageFactory.get(scenicConfig.getStoreType());
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
log.info("开始清理视频文件"); log.info("开始清理视频文件");
List<StorageFileObject> fileObjectList = adapter.listDir(StorageConstant.VLOG_PATH); List<StorageFileObject> fileObjectList = adapter.listDir(StorageConstant.VLOG_PATH);
fileObjectList.parallelStream().forEach(fileObject -> { fileObjectList.parallelStream().forEach(fileObject -> {