feat:fwd下单优化
This commit is contained in:
@@ -3,4 +3,8 @@ package com.xiang.xservice.fwd.constants;
|
|||||||
public class CodeConstants {
|
public class CodeConstants {
|
||||||
public static final Integer SUCCESS = 10000;
|
public static final Integer SUCCESS = 10000;
|
||||||
public static final Integer LIMIT = 47009;
|
public static final Integer LIMIT = 47009;
|
||||||
|
|
||||||
|
public static final Integer TOKEN_EXPIRED = 11004;
|
||||||
|
|
||||||
|
public static final Integer SYSTEM_ERROR = 90008;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,4 +37,9 @@ public class UrlConstants {
|
|||||||
* 查询观影人列表
|
* 查询观影人列表
|
||||||
*/
|
*/
|
||||||
public final static String PROJECT_AUDIENCE_MEMBER_INFO = BASE_URL + "/member/member/bearer/app/list";
|
public final static String PROJECT_AUDIENCE_MEMBER_INFO = BASE_URL + "/member/member/bearer/app/list";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务端时间
|
||||||
|
*/
|
||||||
|
public final static String PERFORMANCE_SERVER_TIME = BASE_URL + "/performance/app/project/serverTime";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.xiang.xservice.fwd.mapper.FwdUserConfigMapper;
|
|||||||
import com.xiang.xservice.fwd.service.DingTalkScriptFWDService;
|
import com.xiang.xservice.fwd.service.DingTalkScriptFWDService;
|
||||||
import com.xiang.xservice.fwd.service.IPerformService;
|
import com.xiang.xservice.fwd.service.IPerformService;
|
||||||
import com.xiang.xservice.fwd.service.IPerformServiceHttp;
|
import com.xiang.xservice.fwd.service.IPerformServiceHttp;
|
||||||
|
import com.xiang.xservice.fwd.utils.TimeSyncUtils;
|
||||||
import com.xiang.xservice.schedule.core.DynamicTaskScheduler;
|
import com.xiang.xservice.schedule.core.DynamicTaskScheduler;
|
||||||
import com.xiang.xservice.schedule.entity.ScheduledTaskEntity;
|
import com.xiang.xservice.schedule.entity.ScheduledTaskEntity;
|
||||||
import com.xiang.xservice.schedule.entity.TaskConfig;
|
import com.xiang.xservice.schedule.entity.TaskConfig;
|
||||||
@@ -78,10 +79,11 @@ public class FwdImportantMsgJob {
|
|||||||
for (ScheduledTaskEntity taskEntity : taskList) {
|
for (ScheduledTaskEntity taskEntity : taskList) {
|
||||||
HashMap params = com.alibaba.fastjson2.JSON.parseObject(taskEntity.getParameters(), HashMap.class);
|
HashMap params = com.alibaba.fastjson2.JSON.parseObject(taskEntity.getParameters(), HashMap.class);
|
||||||
FwdOrderTaskParam param = MapUtils.isEmpty(params) ? new FwdOrderTaskParam(null, taskEntity.getId()) : new FwdOrderTaskParam((Long) params.get("projectId"), taskEntity.getId());
|
FwdOrderTaskParam param = MapUtils.isEmpty(params) ? new FwdOrderTaskParam(null, taskEntity.getId()) : new FwdOrderTaskParam((Long) params.get("projectId"), taskEntity.getId());
|
||||||
LocalDateTime runTime = taskEntity.getRunTime().isBefore(LocalDateTime.now()) ? LocalDateTime.now().plusMinutes(1) : taskEntity.getRunTime();
|
LocalDateTime runTime = taskEntity.getRunTime().isBefore(TimeSyncUtils.now()) ? TimeSyncUtils.now() : taskEntity.getRunTime();
|
||||||
dynamicTaskScheduler.schedule(
|
dynamicTaskScheduler.schedule(
|
||||||
new TaskConfig(taskEntity.getId(), taskEntity.getTaskName(), taskEntity.getTaskGroup(), runTime, params),
|
new TaskConfig(taskEntity.getId(), taskEntity.getTaskName(), taskEntity.getTaskGroup(), runTime, params),
|
||||||
new TicketGrabTask(fwdUserConfigMapper, fwdAudienceConfigMapper, iPerformService, param, dynamicTaskSchedulerService)
|
new TicketGrabTask(fwdUserConfigMapper, fwdAudienceConfigMapper, iPerformService, param, dynamicTaskSchedulerService),
|
||||||
|
TimeSyncUtils.now()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,7 +97,7 @@ public class FwdImportantMsgJob {
|
|||||||
performConfigMapper.delPerforms();
|
performConfigMapper.delPerforms();
|
||||||
|
|
||||||
// 查询所有即将今天预售的演唱会信息
|
// 查询所有即将今天预售的演唱会信息
|
||||||
LocalDate now = LocalDate.now();
|
LocalDate now = TimeSyncUtils.now().toLocalDate();
|
||||||
List<FPerformProjectInfo> saleTodayData = performProjectInfoMapper.getPreSaleTodayData(now.atTime(0, 0, 0), now.atTime(23, 59, 59));
|
List<FPerformProjectInfo> saleTodayData = performProjectInfoMapper.getPreSaleTodayData(now.atTime(0, 0, 0), now.atTime(23, 59, 59));
|
||||||
if (CollectionUtils.isEmpty(saleTodayData)) {
|
if (CollectionUtils.isEmpty(saleTodayData)) {
|
||||||
log.info("【芬玩岛】 今天:{}暂无预售的演唱会门票信息.", now);
|
log.info("【芬玩岛】 今天:{}暂无预售的演唱会门票信息.", now);
|
||||||
@@ -124,7 +126,8 @@ public class FwdImportantMsgJob {
|
|||||||
new TaskConfig(taskId, "芬玩岛演唱会抢票-【" + data.getProjectName() + "】", TaskGroupEnum.SERVICE_FWD_SCHEDULE.getCode(),
|
new TaskConfig(taskId, "芬玩岛演唱会抢票-【" + data.getProjectName() + "】", TaskGroupEnum.SERVICE_FWD_SCHEDULE.getCode(),
|
||||||
runTime, params),
|
runTime, params),
|
||||||
new TicketGrabTask(fwdUserConfigMapper, fwdAudienceConfigMapper, iPerformService,
|
new TicketGrabTask(fwdUserConfigMapper, fwdAudienceConfigMapper, iPerformService,
|
||||||
new FwdOrderTaskParam(data.getProjectId(), taskId), dynamicTaskSchedulerService));
|
new FwdOrderTaskParam(data.getProjectId(), taskId), dynamicTaskSchedulerService),
|
||||||
|
TimeSyncUtils.now());
|
||||||
savaTask(data, taskId, params);
|
savaTask(data, taskId, params);
|
||||||
}
|
}
|
||||||
msg.append("请注意进行数据库配置的更改!");
|
msg.append("请注意进行数据库配置的更改!");
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.xiang.xservice.fwd.schedule;
|
||||||
|
|
||||||
|
import com.xiang.xservice.fwd.service.IPerformServiceHttp;
|
||||||
|
import com.xiang.xservice.fwd.utils.TimeSyncUtils;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: xiang
|
||||||
|
* @Date: 2025-09-30 14:56
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class FwdTimeSyncJob {
|
||||||
|
|
||||||
|
private final IPerformServiceHttp performServiceHttp;
|
||||||
|
@Scheduled(fixedRate = 60_000) // 每分钟执行一次
|
||||||
|
public void syncTime() {
|
||||||
|
try {
|
||||||
|
// 调用对方接口
|
||||||
|
Long timeStamp = performServiceHttp.getServerTimeStamp();
|
||||||
|
if (Objects.equals(timeStamp,-1L)) {
|
||||||
|
log.info("请求服务器时间失败!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TimeSyncUtils.syncWithServer(timeStamp);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("同步时间失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,5 +54,11 @@ public interface IPerformServiceHttp {
|
|||||||
*/
|
*/
|
||||||
List<AudienceMemberInfo> getAudienceMemberInfo(String token);
|
List<AudienceMemberInfo> getAudienceMemberInfo(String token);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http请求获取时间
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Long getServerTimeStamp();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.springframework.stereotype.Service;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -100,6 +101,11 @@ public class PerformServiceHttpServiceImpl implements IPerformServiceHttp {
|
|||||||
}
|
}
|
||||||
return projectOrderCreateResp;
|
return projectOrderCreateResp;
|
||||||
}
|
}
|
||||||
|
if (Objects.nonNull(code) && Objects.equals(code, CodeConstants.LIMIT)) {
|
||||||
|
Integer waitTime = new Random().nextInt(10);
|
||||||
|
log.info("触发FWD限流机制,等待:{}秒后重新发送。", waitTime);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +176,23 @@ public class PerformServiceHttpServiceImpl implements IPerformServiceHttp {
|
|||||||
return Lists.newArrayList();
|
return Lists.newArrayList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getServerTimeStamp() {
|
||||||
|
String respStr = HttpUtils.doGet(UrlConstants.PERFORMANCE_SERVER_TIME, buildFWDHeaders(null), null);
|
||||||
|
if (StringUtils.isBlank(respStr)) {
|
||||||
|
return -1L;
|
||||||
|
}
|
||||||
|
JSONObject jsonObject = JSON.parseObject(respStr);
|
||||||
|
if (Objects.nonNull(jsonObject)) {
|
||||||
|
Integer code = (Integer) jsonObject.get("code");
|
||||||
|
if (Objects.equals(code, CodeConstants.SUCCESS)) {
|
||||||
|
Long timestamp = (Long) jsonObject.get("data");
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1L;
|
||||||
|
}
|
||||||
|
|
||||||
private Map<String, String> buildFWDHeaders(String token) {
|
private Map<String, String> buildFWDHeaders(String token) {
|
||||||
Map<String, String> headers = Maps.newHashMap();
|
Map<String, String> headers = Maps.newHashMap();
|
||||||
headers.put("Host", "api.livelab.com.cn");
|
headers.put("Host", "api.livelab.com.cn");
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import com.xiang.xservice.http.helper.HttpRequestHelper;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@@ -87,6 +88,23 @@ public class PerformServiceImpl implements IPerformService {
|
|||||||
if (1 == fPerformSeatInfo.getSoldOut()) {
|
if (1 == fPerformSeatInfo.getSoldOut()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
ProjectOrderCreateReq projectOrderCreateReq = buildReq(projectId, frequentIds, fPerformSeatInfo);
|
||||||
|
for (int i = 1; i <= 10; i++) {
|
||||||
|
ProjectOrderCreateResp projectOrder = httpRequestHelper.fetchWithRetry(() -> performServiceHttp.createProjectOrder(projectOrderCreateReq, availableUser.get(0).getToken()), "create-project-order");
|
||||||
|
if (Objects.nonNull(projectOrder)) {
|
||||||
|
log.info("下单成功,订单信息:{}", JSONObject.toJSONString(projectOrder));
|
||||||
|
String msg = "【芬玩岛】下单成功✅✅✅,演出名称:" + performByProjectId.getProjectName() + ",请在2分钟内完成付款!";
|
||||||
|
dingTalkService.sendScriptMsg(msg);
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dingTalkService.sendScriptMsg("【芬玩岛】下单失败❌❌❌,演出名称:" + performByProjectId.getProjectName());
|
||||||
|
return Boolean.FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static ProjectOrderCreateReq buildReq(Long projectId, List<Long> frequentIds, FPerformSeatInfo fPerformSeatInfo) {
|
||||||
ProjectOrderCreateReq projectOrderCreateReq = new ProjectOrderCreateReq();
|
ProjectOrderCreateReq projectOrderCreateReq = new ProjectOrderCreateReq();
|
||||||
projectOrderCreateReq.setDeliveryType(1);
|
projectOrderCreateReq.setDeliveryType(1);
|
||||||
projectOrderCreateReq.setContactName("朱吉祥");
|
projectOrderCreateReq.setContactName("朱吉祥");
|
||||||
@@ -102,18 +120,7 @@ public class PerformServiceImpl implements IPerformService {
|
|||||||
projectOrderCreateReq.setBlackBox("0");
|
projectOrderCreateReq.setBlackBox("0");
|
||||||
projectOrderCreateReq.setCombineTicketVos(null);
|
projectOrderCreateReq.setCombineTicketVos(null);
|
||||||
projectOrderCreateReq.setOrdinaryTicketVos(null);
|
projectOrderCreateReq.setOrdinaryTicketVos(null);
|
||||||
for (int i = 1; i <= 10; i++) {
|
return projectOrderCreateReq;
|
||||||
ProjectOrderCreateResp projectOrder = httpRequestHelper.fetchWithRetry(() -> performServiceHttp.createProjectOrder(projectOrderCreateReq, availableUser.get(0).getToken()), "create-project-order");
|
|
||||||
if (Objects.nonNull(projectOrder)) {
|
|
||||||
log.info("下单成功,订单信息:{}", JSONObject.toJSONString(projectOrder));
|
|
||||||
String msg = "【芬玩岛】下单成功✅✅✅,演出名称:" + performByProjectId.getProjectName() + ",请在2分钟内完成付款!";
|
|
||||||
dingTalkService.sendScriptMsg(msg);
|
|
||||||
return Boolean.TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dingTalkService.sendScriptMsg("【芬玩岛】下单失败❌❌❌,演出名称:" + performByProjectId.getProjectName());
|
|
||||||
return Boolean.FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.xiang.xservice.fwd.utils;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: xiang
|
||||||
|
* @Date: 2025-09-30 14:58
|
||||||
|
*/
|
||||||
|
public class TimeSyncUtils {
|
||||||
|
private static volatile long offset = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化/更新偏移量
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static void syncWithServer(long serverTime) {
|
||||||
|
long localTime = System.currentTimeMillis();
|
||||||
|
offset = serverTime - localTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取同步后的时间戳
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static long currentTimeMillis() {
|
||||||
|
return System.currentTimeMillis() + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取同步后的 LocalDateTime
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static LocalDateTime now() {
|
||||||
|
return LocalDateTime.ofInstant(
|
||||||
|
Instant.ofEpochMilli(currentTimeMillis()),
|
||||||
|
ZoneId.systemDefault()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user