指定设备提前预约
This commit is contained in:
parent
1eb636d402
commit
a016622cc9
192
src/main/java/com/ycwl/basic/biz/TaskStatusBiz.java
Normal file
192
src/main/java/com/ycwl/basic/biz/TaskStatusBiz.java
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
package com.ycwl.basic.biz;
|
||||||
|
|
||||||
|
import com.ycwl.basic.mapper.FaceMapper;
|
||||||
|
import com.ycwl.basic.mapper.TaskMapper;
|
||||||
|
import com.ycwl.basic.mapper.VideoMapper;
|
||||||
|
import com.ycwl.basic.model.mobile.goods.VideoTaskStatusVO;
|
||||||
|
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
|
||||||
|
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
|
||||||
|
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.resp.TemplateRespVO;
|
||||||
|
import com.ycwl.basic.model.pc.video.entity.VideoEntity;
|
||||||
|
import com.ycwl.basic.repository.FaceRepository;
|
||||||
|
import com.ycwl.basic.repository.TemplateRepository;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class TaskStatusBiz {
|
||||||
|
public static final String TASK_STATUS_USER_CACHE_KEY = "task:status:user:%s:face:%s";
|
||||||
|
public static final String TASK_STATUS_FACE_CACHE_KEY = "task:status:face:%s";
|
||||||
|
public static final String TASK_STATUS_FACE_CACHE_KEY_CUT = "task:status:face:%s:cut";
|
||||||
|
public static final String TASK_STATUS_FACE_CACHE_KEY_TEMPLATE = "task:status:face:%s:tpl:%s";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate<String, String> redisTemplate;
|
||||||
|
@Autowired
|
||||||
|
private FaceRepository faceRepository;
|
||||||
|
@Autowired
|
||||||
|
private TemplateRepository templateRepository;
|
||||||
|
@Autowired
|
||||||
|
private FaceMapper faceMapper;
|
||||||
|
@Autowired
|
||||||
|
private TaskMapper taskMapper;
|
||||||
|
@Autowired
|
||||||
|
private VideoMapper videoMapper;
|
||||||
|
@Autowired
|
||||||
|
private TemplateBiz templateBiz;
|
||||||
|
|
||||||
|
public boolean getUserHaveFace(Long userId, Long faceId) {
|
||||||
|
if (userId == null || faceId == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (redisTemplate.hasKey(String.format(TASK_STATUS_USER_CACHE_KEY, userId, faceId))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
FaceEntity face = faceRepository.getFace(faceId);
|
||||||
|
if (face == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (face.getMemberId().equals(userId)) {
|
||||||
|
redisTemplate.opsForValue().set(String.format(TASK_STATUS_USER_CACHE_KEY, userId, faceId), "1", 3600, TimeUnit.SECONDS);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFaceCutStatus(Long faceId, int status) {
|
||||||
|
redisTemplate.opsForValue().set(String.format(TASK_STATUS_FACE_CACHE_KEY_CUT, faceId), String.valueOf(status), 3600, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFaceTemplateStatus(Long faceId, Long templateId, Long videoId) {
|
||||||
|
redisTemplate.opsForValue().set(String.format(TASK_STATUS_FACE_CACHE_KEY_TEMPLATE, faceId, templateId), String.valueOf(videoId), 3600, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VideoTaskStatusVO getScenicUserStatus(Long scenicId, Long userId) {
|
||||||
|
FaceRespVO lastFace = faceMapper.findLastFaceByScenicAndUserId(scenicId, userId);
|
||||||
|
VideoTaskStatusVO response = new VideoTaskStatusVO();
|
||||||
|
if (lastFace == null) {
|
||||||
|
response.setStatus(-1);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
return getFaceStatus(lastFace.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public VideoTaskStatusVO getFaceStatus(Long faceId) {
|
||||||
|
FaceEntity face = faceRepository.getFace(faceId);
|
||||||
|
VideoTaskStatusVO response = new VideoTaskStatusVO();
|
||||||
|
if (face == null) {
|
||||||
|
response.setStatus(-1);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
response.setScenicId(face.getScenicId());
|
||||||
|
response.setFaceId(faceId);
|
||||||
|
List<TemplateRespVO> templateList = templateRepository.getTemplateListByScenicId(face.getScenicId());
|
||||||
|
response.setMaxCount(templateList.size());
|
||||||
|
int alreadyFinished = 0;
|
||||||
|
for (TemplateRespVO template : templateList) {
|
||||||
|
response.setTemplateId(template.getId());
|
||||||
|
long videoId = getFaceTemplateVideoId(faceId, template.getId());
|
||||||
|
if (videoId <= 0) {
|
||||||
|
response.setStatus(2);
|
||||||
|
} else {
|
||||||
|
response.setVideoId(videoId);
|
||||||
|
alreadyFinished++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response.setCount(alreadyFinished);
|
||||||
|
if (alreadyFinished == 0) {
|
||||||
|
response.setStatus(0);
|
||||||
|
} else {
|
||||||
|
response.setStatus(1);
|
||||||
|
}
|
||||||
|
if (alreadyFinished == 0) {
|
||||||
|
int faceCutStatus = getFaceCutStatus(faceId);
|
||||||
|
if (faceCutStatus != 1) {
|
||||||
|
// 正在切片
|
||||||
|
if (templateBiz.determineTemplateCanGenerate(templateList.get(0).getId(), faceId, false)) {
|
||||||
|
response.setStatus(2);
|
||||||
|
} else {
|
||||||
|
response.setStatus(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VideoTaskStatusVO getFaceTemplateStatus(Long faceId, Long templateId) {
|
||||||
|
FaceEntity face = faceRepository.getFace(faceId);
|
||||||
|
VideoTaskStatusVO response = new VideoTaskStatusVO();
|
||||||
|
if (face == null) {
|
||||||
|
response.setStatus(-1);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
response.setScenicId(face.getScenicId());
|
||||||
|
response.setFaceId(faceId);
|
||||||
|
response.setTemplateId(templateId);
|
||||||
|
long videoId = getFaceTemplateVideoId(faceId, templateId);
|
||||||
|
if (videoId < 0) {
|
||||||
|
int faceCutStatus = getFaceCutStatus(faceId);
|
||||||
|
if (faceCutStatus != 1) {
|
||||||
|
// 正在切片
|
||||||
|
response.setStatus(2);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
} else if (videoId == 0) {
|
||||||
|
response.setStatus(2);
|
||||||
|
} else {
|
||||||
|
response.setVideoId(videoId);
|
||||||
|
response.setStatus(1);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFaceCutStatus(Long faceId) {
|
||||||
|
if (redisTemplate.hasKey(String.format(TASK_STATUS_FACE_CACHE_KEY_CUT, faceId))) {
|
||||||
|
String status = redisTemplate.opsForValue().get(String.format(TASK_STATUS_FACE_CACHE_KEY_CUT, faceId));
|
||||||
|
if (status != null) {
|
||||||
|
return Integer.parseInt(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getFaceTemplateVideoId(Long faceId, Long templateId) {
|
||||||
|
if (redisTemplate.hasKey(String.format(TASK_STATUS_FACE_CACHE_KEY_TEMPLATE, faceId, templateId))) {
|
||||||
|
String status = redisTemplate.opsForValue().get(String.format(TASK_STATUS_FACE_CACHE_KEY_TEMPLATE, faceId, templateId));
|
||||||
|
if (status != null) {
|
||||||
|
return Long.parseLong(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TaskReqQuery taskReqQuery = new TaskReqQuery();
|
||||||
|
taskReqQuery.setFaceId(faceId);
|
||||||
|
taskReqQuery.setTemplateId(templateId);
|
||||||
|
List<TaskRespVO> list = taskMapper.list(taskReqQuery);
|
||||||
|
Optional<TaskRespVO> min = list.stream().min(Comparator.comparing(TaskRespVO::getCreateTime));
|
||||||
|
if (min.isPresent()) {
|
||||||
|
TaskRespVO task = min.get();
|
||||||
|
long taskStatus = 0;
|
||||||
|
if (task.getStatus() == 1) {
|
||||||
|
// 已完成
|
||||||
|
VideoEntity video = videoMapper.findByTaskId(task.getId());
|
||||||
|
if (video != null) {
|
||||||
|
taskStatus = video.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setFaceTemplateStatus(faceId, templateId, taskStatus);
|
||||||
|
} else {
|
||||||
|
// 从来没生成过
|
||||||
|
setFaceTemplateStatus(faceId, templateId, -1L);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package com.ycwl.basic.controller.mobile;
|
package com.ycwl.basic.controller.mobile;
|
||||||
|
|
||||||
import com.ycwl.basic.annotation.IgnoreToken;
|
import com.ycwl.basic.annotation.IgnoreToken;
|
||||||
|
import com.ycwl.basic.biz.TaskStatusBiz;
|
||||||
import com.ycwl.basic.constant.BaseContextHandler;
|
import com.ycwl.basic.constant.BaseContextHandler;
|
||||||
import com.ycwl.basic.exception.CheckTokenException;
|
import com.ycwl.basic.exception.CheckTokenException;
|
||||||
import com.ycwl.basic.model.jwt.JwtInfo;
|
import com.ycwl.basic.model.jwt.JwtInfo;
|
||||||
@ -31,6 +32,8 @@ public class AppGoodsController {
|
|||||||
private GoodsService goodsService;
|
private GoodsService goodsService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private TaskService taskService;
|
private TaskService taskService;
|
||||||
|
@Autowired
|
||||||
|
private TaskStatusBiz taskStatusBiz;
|
||||||
|
|
||||||
@ApiOperation("商品列表")
|
@ApiOperation("商品列表")
|
||||||
@PostMapping("/goodsList")
|
@PostMapping("/goodsList")
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.ycwl.basic.controller.mobile;
|
package com.ycwl.basic.controller.mobile;
|
||||||
|
|
||||||
import com.ycwl.basic.annotation.IgnoreLogReq;
|
import com.ycwl.basic.annotation.IgnoreLogReq;
|
||||||
|
import com.ycwl.basic.biz.TaskStatusBiz;
|
||||||
import com.ycwl.basic.model.jwt.JwtInfo;
|
import com.ycwl.basic.model.jwt.JwtInfo;
|
||||||
import com.ycwl.basic.model.mobile.goods.VideoTaskReq;
|
import com.ycwl.basic.model.mobile.goods.VideoTaskReq;
|
||||||
import com.ycwl.basic.model.mobile.goods.VideoTaskStatusVO;
|
import com.ycwl.basic.model.mobile.goods.VideoTaskStatusVO;
|
||||||
@ -24,6 +25,8 @@ public class AppTaskController {
|
|||||||
private GoodsService goodsService;
|
private GoodsService goodsService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private TaskService taskService;
|
private TaskService taskService;
|
||||||
|
@Autowired
|
||||||
|
private TaskStatusBiz taskStatusBiz;
|
||||||
|
|
||||||
@GetMapping("/face/{faceId}")
|
@GetMapping("/face/{faceId}")
|
||||||
@IgnoreLogReq
|
@IgnoreLogReq
|
||||||
|
@ -273,7 +273,9 @@ public class ViidController {
|
|||||||
faceSampleMapper.add(faceSample);
|
faceSampleMapper.add(faceSample);
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
taskFaceService.addFaceSample(faceSample.getId());
|
taskFaceService.addFaceSample(faceSample.getId());
|
||||||
|
if (deviceConfig != null && Integer.valueOf(1).equals(deviceConfig.getEnablePreBook())) {
|
||||||
DynamicTaskGenerator.addTask(faceSample.getId());
|
DynamicTaskGenerator.addTask(faceSample.getId());
|
||||||
|
}
|
||||||
}).start();
|
}).start();
|
||||||
for (SubImageInfoObject _subImage : type14ImageList) {
|
for (SubImageInfoObject _subImage : type14ImageList) {
|
||||||
facePosition.setImgHeight(_subImage.getHeight());
|
facePosition.setImgHeight(_subImage.getHeight());
|
||||||
@ -318,7 +320,12 @@ public class ViidController {
|
|||||||
faceSample.setFaceUrl(url);
|
faceSample.setFaceUrl(url);
|
||||||
faceSampleMapper.add(faceSample);
|
faceSampleMapper.add(faceSample);
|
||||||
DynamicTaskGenerator.addTask(faceSample.getId());
|
DynamicTaskGenerator.addTask(faceSample.getId());
|
||||||
|
new Thread(() -> {
|
||||||
taskFaceService.addFaceSample(faceSample.getId());
|
taskFaceService.addFaceSample(faceSample.getId());
|
||||||
|
if (deviceConfig != null && Integer.valueOf(1).equals(deviceConfig.getEnablePreBook())) {
|
||||||
|
DynamicTaskGenerator.addTask(faceSample.getId());
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
log.info("模式1人脸信息入库成功!设备ID:{}", deviceID);
|
log.info("模式1人脸信息入库成功!设备ID:{}", deviceID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,9 @@ public enum StatisticEnum {
|
|||||||
REFUND(5,"退款"),
|
REFUND(5,"退款"),
|
||||||
MESSAGE_PUSH(6,"消息推送"),
|
MESSAGE_PUSH(6,"消息推送"),
|
||||||
DOWNLOAD(8,"下载"),
|
DOWNLOAD(8,"下载"),
|
||||||
CLICK_ON_PAYMENT(9,"点击支付、购买"),
|
CLICK_PAY(9,"点击支付"),
|
||||||
OTHER_ENTER(10,"其他渠道进入"),
|
OTHER_ENTER(10,"其他渠道进入"),
|
||||||
|
SUBMIT_PAYMENT(11,"点击支付"),
|
||||||
SCAN_MARKED_CODE(20,"扫描特殊标记码"),
|
SCAN_MARKED_CODE(20,"扫描特殊标记码"),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
@ -66,7 +66,7 @@ public class AuthInterceptor extends HandlerInterceptorAdapter {
|
|||||||
// 获取 token
|
// 获取 token
|
||||||
String token = getToken(request);
|
String token = getToken(request);
|
||||||
if (StringUtils.isEmpty(token)) {
|
if (StringUtils.isEmpty(token)) {
|
||||||
log.error("==> 请求 header 缺少 Token [{}]", token);
|
log.error("==> 请求 header 缺少 Token [{}], URL [{}]", token, request.getRequestURL());
|
||||||
throw new MissTokenException("请求头缺少token");
|
throw new MissTokenException("请求头缺少token");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,11 +24,12 @@ public interface FaceMapper {
|
|||||||
int deleteByIds(@Param("list") List<Long> ids);
|
int deleteByIds(@Param("list") List<Long> ids);
|
||||||
int update(FaceEntity face);
|
int update(FaceEntity face);
|
||||||
|
|
||||||
FaceRespVO getByMemberId(@Param("userId") Long userId, @Param("scenicId") Long scenicId);
|
FaceRespVO getLatestByMemberId(@Param("userId") Long userId, @Param("scenicId") Long scenicId);
|
||||||
|
|
||||||
int finishedJourney(Long faceId);
|
int finishedJourney(Long faceId);
|
||||||
|
|
||||||
FaceRespVO findLastFaceByUserId(String userId);
|
FaceRespVO findLastFaceByUserId(String userId);
|
||||||
|
FaceRespVO findLastFaceByScenicAndUserId(Long scenicId, Long userId);
|
||||||
|
|
||||||
List<FaceRespVO> listByScenicAndUserId(String scenicId, Long userId);
|
List<FaceRespVO> listByScenicAndUserId(String scenicId, Long userId);
|
||||||
}
|
}
|
||||||
|
@ -26,5 +26,5 @@ public interface FaceSampleMapper {
|
|||||||
List<FaceSampleEntity> listByIds(List<Long> list);
|
List<FaceSampleEntity> listByIds(List<Long> list);
|
||||||
|
|
||||||
FaceSampleEntity getEntity(Long faceSampleId);
|
FaceSampleEntity getEntity(Long faceSampleId);
|
||||||
List<FaceSampleEntity> listEntity(Long scenicId, Date endDate);
|
List<FaceSampleEntity> listEntityBeforeDate(Long scenicId, Date endDate);
|
||||||
}
|
}
|
||||||
|
@ -57,4 +57,5 @@ public class DeviceConfigEntity {
|
|||||||
* 切割时,取人脸后多少秒的视频
|
* 切割时,取人脸后多少秒的视频
|
||||||
*/
|
*/
|
||||||
private BigDecimal cutPost;
|
private BigDecimal cutPost;
|
||||||
|
private Integer enablePreBook;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONObject;
|
|||||||
import com.aliyuncs.facebody.model.v20191230.SearchFaceRequest;
|
import com.aliyuncs.facebody.model.v20191230.SearchFaceRequest;
|
||||||
import com.aliyuncs.facebody.model.v20191230.SearchFaceResponse;
|
import com.aliyuncs.facebody.model.v20191230.SearchFaceResponse;
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.ycwl.basic.model.pc.faceDetectLog.resp.MatchLocalRecord;
|
import com.ycwl.basic.model.pc.faceDetectLog.resp.MatchLocalRecord;
|
||||||
@ -31,6 +32,9 @@ public class FaceDetectLog {
|
|||||||
|
|
||||||
private String matchLocalRecord;
|
private String matchLocalRecord;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private List<SearchFaceResponse.Data.MatchListItem.FaceItemsItem> matchRawRecord;
|
||||||
|
|
||||||
public static FaceDetectLog quickCreate(String reason) {
|
public static FaceDetectLog quickCreate(String reason) {
|
||||||
FaceDetectLog log = new FaceDetectLog();
|
FaceDetectLog log = new FaceDetectLog();
|
||||||
log.reason = reason;
|
log.reason = reason;
|
||||||
|
@ -7,6 +7,7 @@ import java.util.Date;
|
|||||||
@Data
|
@Data
|
||||||
public class MatchLocalRecord {
|
public class MatchLocalRecord {
|
||||||
private Long faceSampleId;
|
private Long faceSampleId;
|
||||||
|
private String deviceName;
|
||||||
private String faceUrl;
|
private String faceUrl;
|
||||||
private Float score;
|
private Float score;
|
||||||
private Float confidence;
|
private Float confidence;
|
||||||
|
@ -43,6 +43,7 @@ public class ScenicConfigEntity {
|
|||||||
* 预约流程,1-预约,2-在线,3-全部
|
* 预约流程,1-预约,2-在线,3-全部
|
||||||
*/
|
*/
|
||||||
private Integer bookRoutine;
|
private Integer bookRoutine;
|
||||||
|
private Integer forceFinishTime;
|
||||||
/**
|
/**
|
||||||
* 样本保存时间
|
* 样本保存时间
|
||||||
*/
|
*/
|
||||||
|
@ -5,28 +5,36 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
|
|||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class FixedRateLimiter {
|
public class FixedRateLimiter implements IRateLimiter {
|
||||||
private final Semaphore semaphore = new Semaphore(1);
|
private final Semaphore semaphore = new Semaphore(1);
|
||||||
private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
|
private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
|
||||||
|
|
||||||
public FixedRateLimiter(int rate, TimeUnit timeUnit) {
|
public FixedRateLimiter(int rate, TimeUnit timeUnit) {
|
||||||
// 启动一个线程每0.5秒释放一个许可
|
// 启动一个线程每0.5秒释放一个许可
|
||||||
scheduler.scheduleAtFixedRate(() -> {
|
scheduler.scheduleAtFixedRate(() -> {
|
||||||
synchronized (semaphore) {
|
|
||||||
if (semaphore.availablePermits() < 1) {
|
if (semaphore.availablePermits() < 1) {
|
||||||
semaphore.release(1);
|
semaphore.release(1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}, rate, rate, timeUnit);
|
}, rate, rate, timeUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void acquire() throws InterruptedException {
|
public void acquire() throws InterruptedException {
|
||||||
synchronized (semaphore) {
|
|
||||||
semaphore.acquire();
|
semaphore.acquire();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
scheduler.shutdown();
|
scheduler.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryAcquire() {
|
||||||
|
return semaphore.tryAcquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException {
|
||||||
|
return semaphore.tryAcquire(timeout, unit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
10
src/main/java/com/ycwl/basic/ratelimiter/IRateLimiter.java
Normal file
10
src/main/java/com/ycwl/basic/ratelimiter/IRateLimiter.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package com.ycwl.basic.ratelimiter;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public interface IRateLimiter {
|
||||||
|
void acquire() throws InterruptedException;
|
||||||
|
void shutdown();
|
||||||
|
boolean tryAcquire();
|
||||||
|
boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException;
|
||||||
|
}
|
@ -6,25 +6,45 @@ import java.util.concurrent.Semaphore;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
||||||
public class SlidingWindowRateLimiter {
|
public class SlidingWindowRateLimiter implements IRateLimiter {
|
||||||
private final Semaphore semaphore;
|
private final Semaphore semaphore;
|
||||||
private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
|
private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
|
||||||
|
|
||||||
public SlidingWindowRateLimiter(int maxRequestsPerSecond) {
|
public SlidingWindowRateLimiter(int maxRequestsPerSecond) {
|
||||||
this.semaphore = new Semaphore(maxRequestsPerSecond);
|
this.semaphore = new Semaphore(maxRequestsPerSecond);
|
||||||
int rate = 1000000 / maxRequestsPerSecond;
|
|
||||||
scheduler.scheduleAtFixedRate(() -> {
|
scheduler.scheduleAtFixedRate(() -> {
|
||||||
if (semaphore.availablePermits() < maxRequestsPerSecond) {
|
if (semaphore.availablePermits() < maxRequestsPerSecond) {
|
||||||
semaphore.release(1);
|
semaphore.release(maxRequestsPerSecond - semaphore.availablePermits());
|
||||||
}
|
}
|
||||||
}, rate, rate, TimeUnit.MICROSECONDS);
|
}, 1, 1, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SlidingWindowRateLimiter(int maxRequests, int perSecond) {
|
||||||
|
this.semaphore = new Semaphore(maxRequests);
|
||||||
|
scheduler.scheduleAtFixedRate(() -> {
|
||||||
|
if (semaphore.availablePermits() < maxRequests) {
|
||||||
|
semaphore.release(maxRequests - semaphore.availablePermits());
|
||||||
|
}
|
||||||
|
}, perSecond, perSecond, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void acquire() throws InterruptedException {
|
public void acquire() throws InterruptedException {
|
||||||
semaphore.acquire();
|
semaphore.acquire();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
scheduler.shutdown();
|
scheduler.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryAcquire() {
|
||||||
|
return semaphore.tryAcquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException {
|
||||||
|
return semaphore.tryAcquire(timeout, unit);
|
||||||
|
}
|
||||||
}
|
}
|
@ -346,7 +346,7 @@ public class GoodsServiceImpl implements GoodsService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VideoTaskStatusVO getTaskStatusByScenicId(Long userId, Long scenicId) {
|
public VideoTaskStatusVO getTaskStatusByScenicId(Long userId, Long scenicId) {
|
||||||
FaceRespVO faceVO = faceMapper.getByMemberId(userId, scenicId);
|
FaceRespVO faceVO = faceMapper.getLatestByMemberId(userId, scenicId);
|
||||||
VideoTaskStatusVO response = new VideoTaskStatusVO();
|
VideoTaskStatusVO response = new VideoTaskStatusVO();
|
||||||
response.setScenicId(scenicId);
|
response.setScenicId(scenicId);
|
||||||
if (faceVO == null) {
|
if (faceVO == null) {
|
||||||
|
@ -326,14 +326,6 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
return ApiResponse.fail("订单添加失败");
|
return ApiResponse.fail("订单添加失败");
|
||||||
}
|
}
|
||||||
//点击支付按钮统计
|
//点击支付按钮统计
|
||||||
OrderRespVO orderRespVO = orderMapper.getById(orderId);
|
|
||||||
StatisticsRecordAddReq statisticsRecordAddReq = new StatisticsRecordAddReq();
|
|
||||||
statisticsRecordAddReq.setMemberId(orderRespVO.getMemberId());
|
|
||||||
statisticsRecordAddReq.setType(StatisticEnum.CLICK_ON_PAYMENT.code);
|
|
||||||
statisticsRecordAddReq.setScenicId(orderRespVO.getScenicId());
|
|
||||||
statisticsRecordAddReq.setMorphId(orderId);
|
|
||||||
statisticsMapper.addStatisticsRecord(statisticsRecordAddReq);
|
|
||||||
|
|
||||||
|
|
||||||
WxPayRespVO wxPayRespVO = initiatePayment(order, orderItems);
|
WxPayRespVO wxPayRespVO = initiatePayment(order, orderItems);
|
||||||
return ApiResponse.success(wxPayRespVO);
|
return ApiResponse.success(wxPayRespVO);
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package com.ycwl.basic.service.task.impl;
|
package com.ycwl.basic.service.task.impl;
|
||||||
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.aliyuncs.exceptions.ClientException;
|
import com.aliyuncs.exceptions.ClientException;
|
||||||
import com.aliyuncs.exceptions.ServerException;
|
|
||||||
import com.aliyuncs.facebody.model.v20191230.AddFaceEntityRequest;
|
import com.aliyuncs.facebody.model.v20191230.AddFaceEntityRequest;
|
||||||
import com.aliyuncs.facebody.model.v20191230.AddFaceRequest;
|
import com.aliyuncs.facebody.model.v20191230.AddFaceRequest;
|
||||||
import com.aliyuncs.facebody.model.v20191230.AddFaceResponse;
|
import com.aliyuncs.facebody.model.v20191230.AddFaceResponse;
|
||||||
@ -16,7 +14,6 @@ import com.aliyuncs.facebody.model.v20191230.ListFaceEntitiesRequest;
|
|||||||
import com.aliyuncs.facebody.model.v20191230.ListFaceEntitiesResponse;
|
import com.aliyuncs.facebody.model.v20191230.ListFaceEntitiesResponse;
|
||||||
import com.aliyuncs.facebody.model.v20191230.SearchFaceRequest;
|
import com.aliyuncs.facebody.model.v20191230.SearchFaceRequest;
|
||||||
import com.aliyuncs.facebody.model.v20191230.SearchFaceResponse;
|
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.biz.OrderBiz;
|
||||||
import com.ycwl.basic.config.FaceDetectConfig;
|
import com.ycwl.basic.config.FaceDetectConfig;
|
||||||
import com.ycwl.basic.constant.FaceConstant;
|
import com.ycwl.basic.constant.FaceConstant;
|
||||||
@ -27,22 +24,20 @@ import com.ycwl.basic.mapper.FaceSampleMapper;
|
|||||||
import com.ycwl.basic.mapper.ScenicMapper;
|
import com.ycwl.basic.mapper.ScenicMapper;
|
||||||
import com.ycwl.basic.mapper.SourceMapper;
|
import com.ycwl.basic.mapper.SourceMapper;
|
||||||
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
|
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
|
||||||
|
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
|
||||||
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
|
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
|
||||||
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
|
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
|
||||||
import com.ycwl.basic.model.pc.faceDetectLog.entity.FaceDetectLog;
|
import com.ycwl.basic.model.pc.faceDetectLog.entity.FaceDetectLog;
|
||||||
import com.ycwl.basic.model.pc.faceDetectLog.resp.MatchLocalRecord;
|
import com.ycwl.basic.model.pc.faceDetectLog.resp.MatchLocalRecord;
|
||||||
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
|
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.faceSample.resp.FaceSampleRespVO;
|
||||||
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.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.MemberSourceEntity;
|
||||||
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
||||||
import com.ycwl.basic.model.task.resp.AddFaceSampleRespVo;
|
import com.ycwl.basic.model.task.resp.AddFaceSampleRespVo;
|
||||||
import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
|
import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
|
||||||
import com.ycwl.basic.ratelimiter.FixedRateLimiter;
|
import com.ycwl.basic.ratelimiter.FixedRateLimiter;
|
||||||
import com.ycwl.basic.ratelimiter.SlidingWindowRateLimiter;
|
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.task.TaskFaceService;
|
import com.ycwl.basic.service.task.TaskFaceService;
|
||||||
@ -55,7 +50,6 @@ 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.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.aliyuncs.DefaultAcsClient;
|
import com.aliyuncs.DefaultAcsClient;
|
||||||
import com.aliyuncs.IAcsClient;
|
import com.aliyuncs.IAcsClient;
|
||||||
@ -103,6 +97,8 @@ public class TaskFaceServiceImpl implements TaskFaceService {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ScenicRepository scenicRepository;
|
private ScenicRepository scenicRepository;
|
||||||
|
@Autowired
|
||||||
|
private DeviceRepository deviceRepository;
|
||||||
|
|
||||||
private IAcsClient getClient() {
|
private IAcsClient getClient() {
|
||||||
DefaultProfile profile = DefaultProfile.getProfile(
|
DefaultProfile profile = DefaultProfile.getProfile(
|
||||||
@ -195,29 +191,13 @@ public class TaskFaceServiceImpl implements TaskFaceService {
|
|||||||
if (matchList.get(0).getFaceItems().isEmpty()) {
|
if (matchList.get(0).getFaceItems().isEmpty()) {
|
||||||
return respVo;
|
return respVo;
|
||||||
}
|
}
|
||||||
List<MatchLocalRecord> records = matchList.get(0).getFaceItems().stream()
|
List<SearchFaceResponse.Data.MatchListItem.FaceItemsItem> records = matchList.get(0).getFaceItems();
|
||||||
.map(item -> {
|
log.setMatchRawRecord(records);
|
||||||
MatchLocalRecord record = new MatchLocalRecord();
|
|
||||||
record.setIdStr(item.getExtraData());
|
|
||||||
record.setFaceSampleId(Long.parseLong(item.getExtraData()));
|
|
||||||
if (StringUtils.isNumeric(item.getDbName())) {
|
|
||||||
FaceSampleEntity faceSample = faceRepository.getFaceSample(record.getFaceSampleId());
|
|
||||||
if (faceSample != null) {
|
|
||||||
record.setFaceUrl(faceSample.getFaceUrl());
|
|
||||||
record.setShotDate(faceSample.getCreateAt());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
record.setFaceUrl(getFaceUrl(record.getFaceSampleId()));
|
|
||||||
}
|
|
||||||
record.setScore(item.getScore());
|
|
||||||
record.setConfidence(item.getConfidence());
|
|
||||||
return record;
|
|
||||||
})
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
log.matchLocalRecord(records);
|
|
||||||
List<Long> faceSampleIds = records.stream()
|
List<Long> faceSampleIds = records.stream()
|
||||||
.filter(record -> record.getScore() > 0.525F)
|
.filter(record -> record.getScore() > 0.525F)
|
||||||
.map(MatchLocalRecord::getFaceSampleId)
|
.map(SearchFaceResponse.Data.MatchListItem.FaceItemsItem::getExtraData)
|
||||||
|
.filter(StringUtils::isNumeric)
|
||||||
|
.map(Long::valueOf)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
respVo.setFirstMatchRate(matchList.get(0).getFaceItems().get(0).getScore());
|
respVo.setFirstMatchRate(matchList.get(0).getFaceItems().get(0).getScore());
|
||||||
respVo.setSampleListIds(faceSampleIds);
|
respVo.setSampleListIds(faceSampleIds);
|
||||||
@ -227,7 +207,33 @@ public class TaskFaceServiceImpl implements TaskFaceService {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
throw new BaseException(e.getMessage());
|
throw new BaseException(e.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
|
new Thread(() -> {
|
||||||
|
if (log.getMatchRawRecord() != null) {
|
||||||
|
List<MatchLocalRecord> collect = log.getMatchRawRecord().parallelStream().map(item -> {
|
||||||
|
MatchLocalRecord record = new MatchLocalRecord();
|
||||||
|
record.setIdStr(item.getExtraData());
|
||||||
|
record.setFaceSampleId(Long.parseLong(item.getExtraData()));
|
||||||
|
if (StringUtils.isNumeric(item.getDbName())) {
|
||||||
|
FaceSampleEntity faceSample = faceRepository.getFaceSample(record.getFaceSampleId());
|
||||||
|
if (faceSample != null) {
|
||||||
|
DeviceEntity device = deviceRepository.getDevice(faceSample.getDeviceId());
|
||||||
|
if (device != null) {
|
||||||
|
record.setDeviceName(device.getName());
|
||||||
|
}
|
||||||
|
record.setFaceUrl(faceSample.getFaceUrl());
|
||||||
|
record.setShotDate(faceSample.getCreateAt());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
record.setFaceUrl(getFaceUrl(record.getFaceSampleId()));
|
||||||
|
}
|
||||||
|
record.setScore(item.getScore());
|
||||||
|
record.setConfidence(item.getConfidence());
|
||||||
|
return record;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
log.setMatchLocalRecord(JSON.toJSONString(collect));
|
||||||
|
}
|
||||||
logMapper.insert(log);
|
logMapper.insert(log);
|
||||||
|
}).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,20 +295,6 @@ public class TaskFaceServiceImpl implements TaskFaceService {
|
|||||||
sampleStoreDay = 7;
|
sampleStoreDay = 7;
|
||||||
}
|
}
|
||||||
Date endDate = DateUtils.addDateDays(new Date(), -(sampleStoreDay + 1));
|
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 listFaceEntitiesRequest = new ListFaceEntitiesRequest();
|
||||||
listFaceEntitiesRequest.setDbName(String.valueOf(scenicId));
|
listFaceEntitiesRequest.setDbName(String.valueOf(scenicId));
|
||||||
listFaceEntitiesRequest.setOrder("asc");
|
listFaceEntitiesRequest.setOrder("asc");
|
||||||
@ -342,6 +334,20 @@ public class TaskFaceServiceImpl implements TaskFaceService {
|
|||||||
}
|
}
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
|
List<FaceSampleEntity> faceSampleList = faceSampleMapper.listEntityBeforeDate(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());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -345,7 +345,8 @@ public class TaskTaskServiceImpl implements TaskService {
|
|||||||
if (templateList == null || templateList.isEmpty()) {
|
if (templateList == null || templateList.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Integer.valueOf(3).equals(scenicConfig.getBookRoutine())) {
|
if (Integer.valueOf(3).equals(scenicConfig.getBookRoutine()) || Integer.valueOf(4).equals(scenicConfig.getBookRoutine())) {
|
||||||
|
// 生成全部视频的逻辑
|
||||||
templateList.forEach(template -> {
|
templateList.forEach(template -> {
|
||||||
createTaskByFaceIdAndTempalteId(faceId, template.getId(), 1);
|
createTaskByFaceIdAndTempalteId(faceId, template.getId(), 1);
|
||||||
});
|
});
|
||||||
|
@ -90,7 +90,7 @@ public class DynamicTaskGenerator {
|
|||||||
queue.add(new Task(faceSampleId, createTime));
|
queue.add(new Task(faceSampleId, createTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(fixedDelay = 500L)
|
@Scheduled(fixedDelay = 1000L)
|
||||||
public void doTask() {
|
public void doTask() {
|
||||||
Task task = queue.poll();
|
Task task = queue.poll();
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
@ -111,7 +111,7 @@ public class DynamicTaskGenerator {
|
|||||||
log.debug("当前景区{},无配置", faceSample.getScenicId());
|
log.debug("当前景区{},无配置", faceSample.getScenicId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!Integer.valueOf(1).equals(scenicConfig.getBookRoutine()) && !Integer.valueOf(3).equals(scenicConfig.getBookRoutine())) {
|
if (!Integer.valueOf(5).equals(scenicConfig.getBookRoutine())) {
|
||||||
log.debug("当前景区{}未启用预约流程,跳过", faceSample.getScenicId());
|
log.debug("当前景区{}未启用预约流程,跳过", faceSample.getScenicId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,15 @@ package com.ycwl.basic.task;
|
|||||||
import com.ycwl.basic.mapper.FaceSampleMapper;
|
import com.ycwl.basic.mapper.FaceSampleMapper;
|
||||||
import com.ycwl.basic.mapper.ScenicMapper;
|
import com.ycwl.basic.mapper.ScenicMapper;
|
||||||
import com.ycwl.basic.mapper.SourceMapper;
|
import com.ycwl.basic.mapper.SourceMapper;
|
||||||
|
import com.ycwl.basic.mapper.VideoMapper;
|
||||||
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.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.model.pc.video.req.VideoReqQuery;
|
||||||
|
import com.ycwl.basic.model.pc.video.resp.VideoRespVO;
|
||||||
|
import com.ycwl.basic.repository.ScenicRepository;
|
||||||
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;
|
||||||
@ -31,6 +36,10 @@ public class FaceCleaner {
|
|||||||
private FaceSampleMapper faceSampleMapper;
|
private FaceSampleMapper faceSampleMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private SourceMapper sourceMapper;
|
private SourceMapper sourceMapper;
|
||||||
|
@Autowired
|
||||||
|
private VideoMapper videoMapper;
|
||||||
|
@Autowired
|
||||||
|
private ScenicRepository scenicRepository;
|
||||||
|
|
||||||
@Scheduled(cron = "0 0 4 * * ?")
|
@Scheduled(cron = "0 0 4 * * ?")
|
||||||
public void clean(){
|
public void clean(){
|
||||||
@ -44,11 +53,43 @@ public class FaceCleaner {
|
|||||||
|
|
||||||
@Scheduled(cron = "0 0 3 * * ?")
|
@Scheduled(cron = "0 0 3 * * ?")
|
||||||
public void deleteExpiredSource(){
|
public void deleteExpiredSource(){
|
||||||
|
ScenicReqQuery scenicQuery = new ScenicReqQuery();
|
||||||
|
List<ScenicRespVO> scenicList = scenicMapper.list(scenicQuery);
|
||||||
|
scenicList.parallelStream().forEach(scenic -> {
|
||||||
|
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenic.getId());
|
||||||
|
if (scenicConfig == null) {
|
||||||
|
log.info("当前景区{},无配置信息", scenic.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int imageSourceExpireDay = 7;
|
||||||
|
int videoSourceExpireDay = 7;
|
||||||
|
if (scenicConfig.getImageSourceStoreDay() != null) {
|
||||||
|
imageSourceExpireDay = scenicConfig.getImageSourceStoreDay();
|
||||||
|
} else {
|
||||||
|
log.info("当前景区{},原始素材保存天数未设置,默认7天", scenic.getName());
|
||||||
|
}
|
||||||
|
if (scenicConfig.getVideoSourceStoreDay() != null) {
|
||||||
|
videoSourceExpireDay = scenicConfig.getVideoSourceStoreDay();
|
||||||
|
} else {
|
||||||
|
log.info("当前景区{},原始素材保存天数未设置,默认7天", scenic.getName());
|
||||||
|
}
|
||||||
|
if (Integer.valueOf(1).equals(scenicConfig.getDisableSourceVideo())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Integer.valueOf(1).equals(scenicConfig.getDisableSourceImage())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.info("当前景区{},开始删除原始素材", scenic.getName());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(cron = "0 0 5 * * ?")
|
@Scheduled(cron = "0 0 5 * * ?")
|
||||||
public void clear(){
|
public void clearOss(){
|
||||||
|
cleanFaceSampleOss();
|
||||||
|
cleanSourceOss();
|
||||||
|
cleanVideoOss();
|
||||||
|
}
|
||||||
|
private void cleanFaceSampleOss() {
|
||||||
log.info("开始清理人脸文件");
|
log.info("开始清理人脸文件");
|
||||||
List<FaceSampleRespVO> faceSampleRespVOS = faceSampleMapper.list(new FaceSampleReqQuery());
|
List<FaceSampleRespVO> faceSampleRespVOS = faceSampleMapper.list(new FaceSampleReqQuery());
|
||||||
IStorageAdapter adapter = StorageFactory.use("faces");
|
IStorageAdapter adapter = StorageFactory.use("faces");
|
||||||
@ -60,4 +101,20 @@ public class FaceCleaner {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
private void cleanSourceOss() {
|
||||||
|
}
|
||||||
|
private void cleanVideoOss() {
|
||||||
|
log.info("开始清理视频文件");
|
||||||
|
List<VideoRespVO> videoRespVOS = videoMapper.list(new VideoReqQuery());
|
||||||
|
IStorageAdapter adapter = StorageFactory.use("video");
|
||||||
|
List<StorageFileObject> fileObjectList = adapter.listDir("");
|
||||||
|
fileObjectList.parallelStream().forEach(fileObject -> {
|
||||||
|
if (videoRespVOS.parallelStream().noneMatch(videoRespVO -> videoRespVO.getVideoUrl().contains(fileObject.getFullPath()))){
|
||||||
|
log.info("删除视频文件:{}", fileObject);
|
||||||
|
adapter.deleteFile(fileObject.getFullPath());
|
||||||
|
} else {
|
||||||
|
log.info("视频文件存在关系:{},未删除", fileObject);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
package com.ycwl.basic.task;
|
package com.ycwl.basic.task;
|
||||||
|
|
||||||
import com.ycwl.basic.biz.OrderBiz;
|
import com.ycwl.basic.biz.OrderBiz;
|
||||||
|
import com.ycwl.basic.biz.TaskStatusBiz;
|
||||||
import com.ycwl.basic.device.DeviceFactory;
|
import com.ycwl.basic.device.DeviceFactory;
|
||||||
import com.ycwl.basic.device.entity.common.FileObject;
|
import com.ycwl.basic.device.entity.common.FileObject;
|
||||||
import com.ycwl.basic.device.operator.IDeviceStorageOperator;
|
import com.ycwl.basic.device.operator.IDeviceStorageOperator;
|
||||||
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
|
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
|
||||||
import com.ycwl.basic.repository.DeviceRepository;
|
import com.ycwl.basic.repository.DeviceRepository;
|
||||||
import com.ycwl.basic.mapper.DeviceMapper;
|
|
||||||
import com.ycwl.basic.mapper.FaceSampleMapper;
|
import com.ycwl.basic.mapper.FaceSampleMapper;
|
||||||
import com.ycwl.basic.mapper.SourceMapper;
|
import com.ycwl.basic.mapper.SourceMapper;
|
||||||
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
|
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
|
||||||
import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity;
|
import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity;
|
||||||
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
|
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
|
||||||
import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO;
|
|
||||||
import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
|
import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
|
||||||
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
||||||
import com.ycwl.basic.repository.TemplateRepository;
|
import com.ycwl.basic.repository.TemplateRepository;
|
||||||
@ -34,7 +33,6 @@ import java.io.InputStreamReader;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
@ -57,6 +55,8 @@ public class VideoPieceGetter {
|
|||||||
private OrderBiz orderBiz;
|
private OrderBiz orderBiz;
|
||||||
@Autowired
|
@Autowired
|
||||||
private TemplateRepository templateRepository;
|
private TemplateRepository templateRepository;
|
||||||
|
@Autowired
|
||||||
|
private TaskStatusBiz taskStatusBiz;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class Task {
|
public static class Task {
|
||||||
@ -97,6 +97,9 @@ public class VideoPieceGetter {
|
|||||||
} else {
|
} else {
|
||||||
templatePlaceholder = null;
|
templatePlaceholder = null;
|
||||||
}
|
}
|
||||||
|
if (task.faceId != null) {
|
||||||
|
taskStatusBiz.setFaceCutStatus(task.faceId, 0);
|
||||||
|
}
|
||||||
AtomicBoolean invoke = new AtomicBoolean(false);
|
AtomicBoolean invoke = new AtomicBoolean(false);
|
||||||
List<String> currentPlaceholder = new ArrayList<>();
|
List<String> currentPlaceholder = new ArrayList<>();
|
||||||
List<FaceSampleEntity> list = faceSampleMapper.listByIds(task.getFaceSampleIds());
|
List<FaceSampleEntity> list = faceSampleMapper.listByIds(task.getFaceSampleIds());
|
||||||
@ -113,7 +116,7 @@ public class VideoPieceGetter {
|
|||||||
.stream()
|
.stream()
|
||||||
.parallel()
|
.parallel()
|
||||||
.forEach(faceSampleList -> {
|
.forEach(faceSampleList -> {
|
||||||
faceSampleList.forEach(faceSample -> {
|
faceSampleList.parallelStream().forEach(faceSample -> {
|
||||||
DeviceEntity device = deviceRepository.getDevice(faceSample.getDeviceId());
|
DeviceEntity device = deviceRepository.getDevice(faceSample.getDeviceId());
|
||||||
DeviceConfigEntity config = deviceRepository.getDeviceConfig(faceSample.getDeviceId());
|
DeviceConfigEntity config = deviceRepository.getDeviceConfig(faceSample.getDeviceId());
|
||||||
|
|
||||||
@ -245,6 +248,9 @@ public class VideoPieceGetter {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
if (task.faceId != null) {
|
||||||
|
taskStatusBiz.setFaceCutStatus(task.faceId, 1);
|
||||||
|
}
|
||||||
if (null != task.getCallback()) {
|
if (null != task.getCallback()) {
|
||||||
if (!invoke.get()) {
|
if (!invoke.get()) {
|
||||||
invoke.set(true);
|
invoke.set(true);
|
||||||
|
@ -4,10 +4,14 @@ import cn.hutool.core.date.DateUtil;
|
|||||||
import com.ycwl.basic.biz.TemplateBiz;
|
import com.ycwl.basic.biz.TemplateBiz;
|
||||||
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.TemplateMapper;
|
import com.ycwl.basic.mapper.TemplateMapper;
|
||||||
import com.ycwl.basic.model.mobile.scenic.content.ContentPageVO;
|
import com.ycwl.basic.model.mobile.scenic.content.ContentPageVO;
|
||||||
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.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.task.resp.SearchFaceRespVo;
|
import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
|
||||||
import com.ycwl.basic.repository.ScenicRepository;
|
import com.ycwl.basic.repository.ScenicRepository;
|
||||||
import com.ycwl.basic.repository.TemplateRepository;
|
import com.ycwl.basic.repository.TemplateRepository;
|
||||||
@ -20,6 +24,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
|||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -38,18 +43,41 @@ public class VideoTaskGenerator {
|
|||||||
private TaskTaskServiceImpl taskTaskService;
|
private TaskTaskServiceImpl taskTaskService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private TemplateMapper templateMapper;
|
private TemplateMapper templateMapper;
|
||||||
|
@Autowired
|
||||||
|
private ScenicMapper scenicMapper;
|
||||||
|
@Autowired
|
||||||
|
private ScenicRepository scenicRepository;
|
||||||
|
|
||||||
// TODO: 可配置,现在赶时间暂时写死
|
// TODO: 可配置,现在赶时间暂时写死
|
||||||
|
|
||||||
@Scheduled(cron = "0 0 18 * * *")
|
@Scheduled(cron = "0 0 * * * *")
|
||||||
public void generateVideoTask() {
|
public void generateVideoTask() {
|
||||||
// 指定,获取指定日期的未完成人脸样本,并生成任务
|
List<ScenicRespVO> scenicList = scenicMapper.list(new ScenicReqQuery());
|
||||||
Long scenicId = 3946669713328836608L;
|
if (scenicList.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTime(new Date());
|
||||||
|
int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
|
||||||
|
calendar.clear();
|
||||||
|
scenicList.parallelStream().forEach(scenic -> {
|
||||||
|
Long scenicId = scenic.getId();
|
||||||
|
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||||
|
if (scenicConfig == null) {
|
||||||
|
log.info("当前景区{},无配置信息", scenic.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Integer.valueOf(1).equals(scenicConfig.getBookRoutine()) || Integer.valueOf(3).equals(scenicConfig.getBookRoutine())) {
|
||||||
|
Integer hour = scenicConfig.getForceFinishTime();
|
||||||
|
if (hour != currentHour) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 定时逻辑
|
||||||
List<ContentPageVO> contentList = templateMapper.listFor(scenicId);
|
List<ContentPageVO> contentList = templateMapper.listFor(scenicId);
|
||||||
if (contentList.isEmpty()) {
|
if (contentList.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Long templateId = contentList.get(0).getTemplateId();
|
|
||||||
FaceReqQuery query = new FaceReqQuery();
|
FaceReqQuery query = new FaceReqQuery();
|
||||||
query.setScenicId(scenicId);
|
query.setScenicId(scenicId);
|
||||||
query.setStartTime(DateUtil.beginOfDay(new Date()));
|
query.setStartTime(DateUtil.beginOfDay(new Date()));
|
||||||
@ -57,6 +85,10 @@ public class VideoTaskGenerator {
|
|||||||
List<FaceRespVO> list = faceMapper.list(query);
|
List<FaceRespVO> list = faceMapper.list(query);
|
||||||
list.stream().parallel().forEach(face -> {
|
list.stream().parallel().forEach(face -> {
|
||||||
taskFaceService.searchFace(face.getId());
|
taskFaceService.searchFace(face.getId());
|
||||||
|
if (Integer.valueOf(3).equals(scenicConfig.getBookRoutine())) {
|
||||||
|
// 全部生成
|
||||||
|
contentList.forEach(content -> {
|
||||||
|
Long templateId = content.getTemplateId();
|
||||||
boolean canAutoGenerate = templateBiz.determineTemplateCanAutoGenerate(templateId, face.getId(), false);
|
boolean canAutoGenerate = templateBiz.determineTemplateCanAutoGenerate(templateId, face.getId(), false);
|
||||||
if (canAutoGenerate) {
|
if (canAutoGenerate) {
|
||||||
log.info("task callback: 自动生成");
|
log.info("task callback: 自动生成");
|
||||||
@ -65,5 +97,18 @@ public class VideoTaskGenerator {
|
|||||||
log.info("task callback: 不自动生成");
|
log.info("task callback: 不自动生成");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
Long templateId = contentList.get(0).getTemplateId();
|
||||||
|
boolean canAutoGenerate = templateBiz.determineTemplateCanAutoGenerate(templateId, face.getId(), false);
|
||||||
|
if (canAutoGenerate) {
|
||||||
|
log.info("task callback: 自动生成");
|
||||||
|
taskTaskService.forceCreateTaskByFaceIdAndTempalteId(face.getId(), templateId);
|
||||||
|
} else {
|
||||||
|
log.info("task callback: 不自动生成");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,8 @@
|
|||||||
online_check = #{onlineCheck},
|
online_check = #{onlineCheck},
|
||||||
online_max_interval = #{onlineMaxInterval},
|
online_max_interval = #{onlineMaxInterval},
|
||||||
cut_pre = #{cutPre},
|
cut_pre = #{cutPre},
|
||||||
cut_post = #{cutPost}
|
cut_post = #{cutPost},
|
||||||
|
enable_pre_book = #{enablePreBook}
|
||||||
where id = #{id}
|
where id = #{id}
|
||||||
</update>
|
</update>
|
||||||
<update id="updateEntity">
|
<update id="updateEntity">
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
from face
|
from face
|
||||||
where id = #{id}
|
where id = #{id}
|
||||||
</select>
|
</select>
|
||||||
<select id="getByMemberId" resultType="com.ycwl.basic.model.pc.face.resp.FaceRespVO">
|
<select id="getLatestByMemberId" resultType="com.ycwl.basic.model.pc.face.resp.FaceRespVO">
|
||||||
select id, scenic_id, member_id, face_url,score, match_sample_ids, first_match_rate, match_result, create_at, update_at
|
select id, scenic_id, member_id, face_url,score, match_sample_ids, first_match_rate, match_result, create_at, update_at
|
||||||
from face
|
from face
|
||||||
where member_id = #{userId} and scenic_id = #{scenicId}
|
where member_id = #{userId} and scenic_id = #{scenicId}
|
||||||
@ -100,4 +100,11 @@
|
|||||||
where member_id = #{userId} and scenic_id = #{scenicId}
|
where member_id = #{userId} and scenic_id = #{scenicId}
|
||||||
order by update_at desc
|
order by update_at desc
|
||||||
</select>
|
</select>
|
||||||
|
<select id="findLastFaceByScenicAndUserId" resultType="com.ycwl.basic.model.pc.face.resp.FaceRespVO">
|
||||||
|
select id, scenic_id, member_id, face_url,score, match_sample_ids, first_match_rate, match_result, create_at, update_at
|
||||||
|
from face
|
||||||
|
where member_id = #{userId} and scenic_id = #{scenicId}
|
||||||
|
order by update_at desc
|
||||||
|
limit 1
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
@ -101,7 +101,7 @@
|
|||||||
from face_sample
|
from face_sample
|
||||||
where id = #{id}
|
where id = #{id}
|
||||||
</select>
|
</select>
|
||||||
<select id="listEntity" resultType="com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity">
|
<select id="listEntityBeforeDate" resultType="com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity">
|
||||||
select *
|
select *
|
||||||
from face_sample
|
from face_sample
|
||||||
where scenic_id = #{scenicId} and create_at <= #{endDate}
|
where scenic_id = #{scenicId} and create_at <= #{endDate}
|
||||||
|
@ -94,7 +94,8 @@
|
|||||||
disable_source_video=#{disableSourceVideo},
|
disable_source_video=#{disableSourceVideo},
|
||||||
disable_source_image=#{disableSourceImage},
|
disable_source_image=#{disableSourceImage},
|
||||||
video_source_store_day=#{videoSourceStoreDay},
|
video_source_store_day=#{videoSourceStoreDay},
|
||||||
image_source_store_day=#{imageSourceStoreDay}
|
image_source_store_day=#{imageSourceStoreDay},
|
||||||
|
force_finish_time=#{forceFinishTime}
|
||||||
</set>
|
</set>
|
||||||
where id = #{id}
|
where id = #{id}
|
||||||
</update>
|
</update>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user