feat:fwd下单优化
This commit is contained in:
@@ -3,4 +3,8 @@ package com.xiang.xservice.fwd.constants;
|
||||
public class CodeConstants {
|
||||
public static final Integer SUCCESS = 10000;
|
||||
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 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.IPerformService;
|
||||
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.entity.ScheduledTaskEntity;
|
||||
import com.xiang.xservice.schedule.entity.TaskConfig;
|
||||
@@ -78,10 +79,11 @@ public class FwdImportantMsgJob {
|
||||
for (ScheduledTaskEntity taskEntity : taskList) {
|
||||
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());
|
||||
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(
|
||||
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();
|
||||
|
||||
// 查询所有即将今天预售的演唱会信息
|
||||
LocalDate now = LocalDate.now();
|
||||
LocalDate now = TimeSyncUtils.now().toLocalDate();
|
||||
List<FPerformProjectInfo> saleTodayData = performProjectInfoMapper.getPreSaleTodayData(now.atTime(0, 0, 0), now.atTime(23, 59, 59));
|
||||
if (CollectionUtils.isEmpty(saleTodayData)) {
|
||||
log.info("【芬玩岛】 今天:{}暂无预售的演唱会门票信息.", now);
|
||||
@@ -124,7 +126,8 @@ public class FwdImportantMsgJob {
|
||||
new TaskConfig(taskId, "芬玩岛演唱会抢票-【" + data.getProjectName() + "】", TaskGroupEnum.SERVICE_FWD_SCHEDULE.getCode(),
|
||||
runTime, params),
|
||||
new TicketGrabTask(fwdUserConfigMapper, fwdAudienceConfigMapper, iPerformService,
|
||||
new FwdOrderTaskParam(data.getProjectId(), taskId), dynamicTaskSchedulerService));
|
||||
new FwdOrderTaskParam(data.getProjectId(), taskId), dynamicTaskSchedulerService),
|
||||
TimeSyncUtils.now());
|
||||
savaTask(data, taskId, params);
|
||||
}
|
||||
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);
|
||||
|
||||
/**
|
||||
* http请求获取时间
|
||||
* @return
|
||||
*/
|
||||
Long getServerTimeStamp();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.springframework.stereotype.Service;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@@ -100,6 +101,11 @@ public class PerformServiceHttpServiceImpl implements IPerformServiceHttp {
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -170,6 +176,23 @@ public class PerformServiceHttpServiceImpl implements IPerformServiceHttp {
|
||||
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) {
|
||||
Map<String, String> headers = Maps.newHashMap();
|
||||
headers.put("Host", "api.livelab.com.cn");
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.xiang.xservice.http.helper.HttpRequestHelper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@@ -87,21 +88,7 @@ public class PerformServiceImpl implements IPerformService {
|
||||
if (1 == fPerformSeatInfo.getSoldOut()) {
|
||||
continue;
|
||||
}
|
||||
ProjectOrderCreateReq projectOrderCreateReq = new ProjectOrderCreateReq();
|
||||
projectOrderCreateReq.setDeliveryType(1);
|
||||
projectOrderCreateReq.setContactName("朱吉祥");
|
||||
projectOrderCreateReq.setContactPhone("15858717571");
|
||||
projectOrderCreateReq.setPayment(fPerformSeatInfo.getPrice().multiply(BigDecimal.valueOf(frequentIds.size())).setScale(2));
|
||||
projectOrderCreateReq.setTotalPrice(fPerformSeatInfo.getPrice().multiply(BigDecimal.valueOf(frequentIds.size())).setScale(2, BigDecimal.ROUND_HALF_UP));
|
||||
projectOrderCreateReq.setPerformId(fPerformSeatInfo.getPerformId());
|
||||
projectOrderCreateReq.setProjectId(projectId.toString());
|
||||
projectOrderCreateReq.setPrivilegeCodeList(new ArrayList<>());
|
||||
projectOrderCreateReq.setAudienceCount(frequentIds.size());
|
||||
projectOrderCreateReq.setFrequentIds(frequentIds);
|
||||
projectOrderCreateReq.setSeatPlanIds(Collections.singletonList(fPerformSeatInfo.getSeatPlanId()));
|
||||
projectOrderCreateReq.setBlackBox("0");
|
||||
projectOrderCreateReq.setCombineTicketVos(null);
|
||||
projectOrderCreateReq.setOrdinaryTicketVos(null);
|
||||
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)) {
|
||||
@@ -116,6 +103,26 @@ public class PerformServiceImpl implements IPerformService {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static ProjectOrderCreateReq buildReq(Long projectId, List<Long> frequentIds, FPerformSeatInfo fPerformSeatInfo) {
|
||||
ProjectOrderCreateReq projectOrderCreateReq = new ProjectOrderCreateReq();
|
||||
projectOrderCreateReq.setDeliveryType(1);
|
||||
projectOrderCreateReq.setContactName("朱吉祥");
|
||||
projectOrderCreateReq.setContactPhone("15858717571");
|
||||
projectOrderCreateReq.setPayment(fPerformSeatInfo.getPrice().multiply(BigDecimal.valueOf(frequentIds.size())).setScale(2));
|
||||
projectOrderCreateReq.setTotalPrice(fPerformSeatInfo.getPrice().multiply(BigDecimal.valueOf(frequentIds.size())).setScale(2, BigDecimal.ROUND_HALF_UP));
|
||||
projectOrderCreateReq.setPerformId(fPerformSeatInfo.getPerformId());
|
||||
projectOrderCreateReq.setProjectId(projectId.toString());
|
||||
projectOrderCreateReq.setPrivilegeCodeList(new ArrayList<>());
|
||||
projectOrderCreateReq.setAudienceCount(frequentIds.size());
|
||||
projectOrderCreateReq.setFrequentIds(frequentIds);
|
||||
projectOrderCreateReq.setSeatPlanIds(Collections.singletonList(fPerformSeatInfo.getSeatPlanId()));
|
||||
projectOrderCreateReq.setBlackBox("0");
|
||||
projectOrderCreateReq.setCombineTicketVos(null);
|
||||
projectOrderCreateReq.setOrdinaryTicketVos(null);
|
||||
return projectOrderCreateReq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FPerformConfig> getAvailablePerform() {
|
||||
return fwdPerformConfigMapper.getAvailablePerform();
|
||||
|
||||
@@ -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