|
@@ -8,15 +8,21 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
import com.fire.dist.data.DataPool;
|
|
|
import com.fire.dist.service.DistOrderService;
|
|
|
+import com.fire.dist.service.OrderUpdateService;
|
|
|
+import com.fire.dist.utils.WeightRand;
|
|
|
import com.fire.dto.*;
|
|
|
import com.fire.dto.enums.DistributePolicy;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import redis.clients.jedis.JedisCluster;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
import java.util.*;
|
|
|
|
|
|
+import static com.fire.common.constants.RocketTags.*;
|
|
|
+import static com.fire.dto.enums.DistributePolicy.DEFAULT_POLICY;
|
|
|
+import static com.fire.dto.enums.OrderStatus.*;
|
|
|
import static com.fire.dto.enums.Province.QG_ALL;
|
|
|
import static com.fire.dto.enums.RedisKey.CHILD_ORDER_INFO;
|
|
|
import static com.fire.dto.enums.ValidStatus.SUSPEND;
|
|
@@ -32,45 +38,74 @@ public class DistOrderServiceImpl implements DistOrderService {
|
|
|
|
|
|
@Resource
|
|
|
private JedisCluster jedisCluster;
|
|
|
+ @Resource
|
|
|
+ private OrderUpdateService orderUpdateService;
|
|
|
|
|
|
@Override
|
|
|
- public void distOrder(FlowOrderInfo orderInfo) {
|
|
|
+ @Async
|
|
|
+ public void distOrder(String orderStr) {
|
|
|
+
|
|
|
+ FlowOrderInfo orderInfo;
|
|
|
+ ObjectMapper om = new ObjectMapper();
|
|
|
+ try {
|
|
|
+ orderInfo = om.readValue(orderStr, FlowOrderInfo.class);
|
|
|
+ } catch (Exception e) {
|
|
|
+ //TODO 订单解析异常告警
|
|
|
+ log.error("订单消息解析失败,消息体为:" + orderStr, e);
|
|
|
+ return;
|
|
|
+ }
|
|
|
//取客户信息,进行分发校验
|
|
|
FlowAppInfo flowAppInfo = DataPool.flowAppInfoMap.get(orderInfo.getAppId());
|
|
|
Long orderId = orderInfo.getOrderId();
|
|
|
if (flowAppInfo == null) {
|
|
|
+ //未找到客户信息异常,更新为异常
|
|
|
log.error("客户信息为空,请检查缓存机制,本次订单号为:" + orderId);
|
|
|
- //todo 入待发送
|
|
|
+ orderInfo.setStatus(ORDER_EXCEPTION.status());
|
|
|
+ orderInfo.setNote("未获取到该订单对应的客户信息,检查客户信息缓存");
|
|
|
+ orderUpdateService.updateOrder(orderInfo, EXCEPTION_TAG);
|
|
|
return;
|
|
|
}
|
|
|
CustomerInfo customerInfo = flowAppInfo.getCustomerInfo();
|
|
|
if (customerInfo == null) {
|
|
|
+ //未找到客户信息异常,更新为异常
|
|
|
log.error("客户信息为空,请检查缓存机制,本次订单号为:" + orderId);
|
|
|
- //todo 入待发送
|
|
|
+ orderInfo.setStatus(ORDER_WAIT_SEND.status());
|
|
|
+ orderInfo.setNote("未获取到该订单对应的客户信息,检查客户信息缓存");
|
|
|
+ orderUpdateService.updateOrder(orderInfo, EXCEPTION_TAG);
|
|
|
return;
|
|
|
}
|
|
|
//客户是否暂停
|
|
|
if (SUSPEND.status().equals(customerInfo.getStatus())) {
|
|
|
- //todo 入待发送
|
|
|
+ //客户暂停,入待发送
|
|
|
+ orderInfo.setStatus(ORDER_WAIT_SEND.status());
|
|
|
+ orderInfo.setNote("未获取到该订单对应的客户信息,检查客户信息缓存");
|
|
|
+ orderUpdateService.updateOrder(orderInfo, WAIT_TAG);
|
|
|
return;
|
|
|
}
|
|
|
//下单时间
|
|
|
Date applyDate = orderInfo.getApplyDate();
|
|
|
if (applyDate == null) {
|
|
|
- log.error("订单下单时间为空,请检查系统bug,订单号为:" + orderId);
|
|
|
+ //下单时间为空,入异常
|
|
|
+ orderInfo.setStatus(ORDER_WAIT_SEND.status());
|
|
|
+ orderInfo.setNote("下单时间为空,异常请检查代码");
|
|
|
+ orderUpdateService.updateOrder(orderInfo, EXCEPTION_TAG);
|
|
|
return;
|
|
|
}
|
|
|
- int timeOut = flowAppInfo.getTime() * 1000;
|
|
|
+ Integer timeOut = flowAppInfo.getTime();
|
|
|
+
|
|
|
long now = System.currentTimeMillis();
|
|
|
- if (now - applyDate.getTime() > timeOut) {
|
|
|
- //todo 入回调队列
|
|
|
+ if (timeOut != null && now - applyDate.getTime() > timeOut * 1000) {
|
|
|
+ //订单超时失败
|
|
|
+ orderInfo.setStatus(ORDER_FAIL.status());
|
|
|
+ orderInfo.setNote("订单超时,失败");
|
|
|
+ orderUpdateService.updateOrder(orderInfo, FAIL_TAG);
|
|
|
return;
|
|
|
}
|
|
|
//取分发记录
|
|
|
Integer sendCount = orderInfo.getSendCount();
|
|
|
Integer nowSendCount = sendCount == null ? 1 : sendCount + 1;
|
|
|
MobileFlowDispatchRec childOrder = null;
|
|
|
- ObjectMapper om = new ObjectMapper();
|
|
|
+
|
|
|
if (sendCount != null) {
|
|
|
Long childId = orderId + sendCount;
|
|
|
String obj = jedisCluster.hget(CHILD_ORDER_INFO.key(), String.valueOf(childId));
|
|
@@ -85,19 +120,28 @@ public class DistOrderServiceImpl implements DistOrderService {
|
|
|
//找到通道组
|
|
|
ChannelGroup channelGroup = DataPool.channelGroupMap.get(flowAppInfo.getChannelId());
|
|
|
if (channelGroup == null) {
|
|
|
- //todo 入待发送
|
|
|
+ //客户未找到通道组,入待发送
|
|
|
+ orderInfo.setStatus(ORDER_WAIT_SEND.status());
|
|
|
+ orderInfo.setNote("未找到通道组,入待发送");
|
|
|
+ orderUpdateService.updateOrder(orderInfo, WAIT_TAG);
|
|
|
return;
|
|
|
}
|
|
|
//提取通道下面的分发组
|
|
|
Map<Integer, List<DistributeGroup>> distributeGroupsMap = channelGroup.getDistributeGroupsMap();
|
|
|
if (distributeGroupsMap == null) {
|
|
|
- //todo 入待发送
|
|
|
+ //没有合适的分发组
|
|
|
+ orderInfo.setStatus(ORDER_WAIT_SEND.status());
|
|
|
+ orderInfo.setNote("没有合适的分发组,入待发送");
|
|
|
+ orderUpdateService.updateOrder(orderInfo, WAIT_TAG);
|
|
|
return;
|
|
|
}
|
|
|
//找到对应运营商的分发组列表
|
|
|
List<DistributeGroup> distributeGroups = distributeGroupsMap.get(orderInfo.getPhoneOperator());
|
|
|
if (CollectionUtils.isEmpty(distributeGroups)) {
|
|
|
- //todo 入待发送
|
|
|
+ //没有合适的分发组
|
|
|
+ orderInfo.setStatus(ORDER_WAIT_SEND.status());
|
|
|
+ orderInfo.setNote("没有合适的分发组,入待发送");
|
|
|
+ orderUpdateService.updateOrder(orderInfo, WAIT_TAG);
|
|
|
return;
|
|
|
}
|
|
|
//分发记录中存的分发日志
|
|
@@ -116,6 +160,7 @@ public class DistOrderServiceImpl implements DistOrderService {
|
|
|
//选择符合条件的通道产品,存入list中
|
|
|
List<ChannelProductInfo> changeProducts = new ArrayList<>();
|
|
|
//当取不到分发组通道 或者 通道产品时 分发组发送次数+1
|
|
|
+ DistributePolicy policy = DEFAULT_POLICY;
|
|
|
while (batchCount <= flowAppInfo.getTotalCount()) {
|
|
|
//对分发次数取模确定选择分发组
|
|
|
int distributeGroupSize = distributeGroups.size();
|
|
@@ -125,11 +170,11 @@ public class DistOrderServiceImpl implements DistOrderService {
|
|
|
DistributeGroup distributeGroup = distributeGroups.get(distributeIndex);
|
|
|
List<ChannelInfo> channelInfos = distributeGroup.getChannelInfos();
|
|
|
if (CollectionUtils.isEmpty(channelInfos)) {
|
|
|
+ //
|
|
|
batchCount += 1;
|
|
|
continue;
|
|
|
}
|
|
|
- //根据分发组策略进行不同的分发操作
|
|
|
- DistributePolicy policy = DistributePolicy.getByCode(distributeGroup.getPolicy());
|
|
|
+
|
|
|
//当前分发组发送次数的发送记录
|
|
|
Map<Long, Integer> thisLog = recordLog.get(batchCount);
|
|
|
|
|
@@ -148,11 +193,13 @@ public class DistOrderServiceImpl implements DistOrderService {
|
|
|
ChannelProductInfo productInfo = strListMap.get(orderInfo.getAreaCode());
|
|
|
//分省资源
|
|
|
if (productInfo != null) {
|
|
|
+ productInfo.setChannelInfo(channelInfo);
|
|
|
changeProducts.add(productInfo);
|
|
|
}
|
|
|
ChannelProductInfo productInfoAll = strListMap.get(QG_ALL.getCode());
|
|
|
if (productInfoAll != null) {
|
|
|
- changeProducts.add(productInfo);
|
|
|
+ productInfoAll.setChannelInfo(channelInfo);
|
|
|
+ changeProducts.add(productInfoAll);
|
|
|
}
|
|
|
|
|
|
}
|
|
@@ -162,24 +209,93 @@ public class DistOrderServiceImpl implements DistOrderService {
|
|
|
batchCount += 1;
|
|
|
} else {
|
|
|
//如果 取到了产品 那么退出
|
|
|
+ //取到分发组策略
|
|
|
+ policy = DistributePolicy.getByCode(distributeGroup.getPolicy());
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- //策略
|
|
|
-// switch (policy) {
|
|
|
-// case COST_PRIOR -> {
|
|
|
-//
|
|
|
-// }
|
|
|
-// case SPEED_PRIOR -> {
|
|
|
-// for (ChannelInfo channelInfo : channelInfos) {
|
|
|
-// //根据产品价格提取通道
|
|
|
-//
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-// }
|
|
|
+ //最终都没取到有两种情况 1是分发过找不到 2是没分发过找不到
|
|
|
+ if (CollectionUtils.isEmpty(changeProducts)) {
|
|
|
+ orderInfo.setSendCount(nowSendCount);
|
|
|
+ orderInfo.setBatchCount(batchCount);
|
|
|
+ //分发过那么直接入失败队列
|
|
|
+ if (childOrder != null) {
|
|
|
+ orderInfo.setStatus(ORDER_FAIL.status());
|
|
|
+ orderInfo.setNote("达到最大重试次数,失败");
|
|
|
+ orderUpdateService.updateOrder(orderInfo, FAIL_TAG);
|
|
|
+ } else {
|
|
|
+ //没有合适的通道
|
|
|
+ orderInfo.setStatus(ORDER_WAIT_SEND.status());
|
|
|
+ orderInfo.setNote("没有合适的通道,入待发送");
|
|
|
+ orderUpdateService.updateOrder(orderInfo, WAIT_TAG);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //找到了就根据策略来分发
|
|
|
+ //策略 最终选择到的产品
|
|
|
+ ChannelProductInfo changeChannelProduct = null;
|
|
|
+ switch (policy) {
|
|
|
+ case COST_PRIOR -> {
|
|
|
+ //成本优先 按成本排序 升序排列
|
|
|
+ changeProducts.sort(Comparator.comparingLong(ChannelProductInfo::getPrice));
|
|
|
+ //提取最低成本
|
|
|
+ List<ChannelProductInfo> minList = new ArrayList<>(3);
|
|
|
+ for (ChannelProductInfo productInfo : changeProducts) {
|
|
|
+ if (productInfo.getPrice().equals(changeProducts.get(0).getPrice())) {
|
|
|
+ minList.add(productInfo);
|
|
|
+ } else {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //取出最低成本的通道 按吞吐量优先
|
|
|
+ changeChannelProduct = WeightRand.nextItem(minList);
|
|
|
+ }
|
|
|
+ case THROUGHPUT_PRIOR -> changeChannelProduct = WeightRand.nextItem(changeProducts);
|
|
|
+ }
|
|
|
+ if (changeChannelProduct != null) {
|
|
|
+ orderInfo.setSendCount(nowSendCount);
|
|
|
+ orderInfo.setBatchCount(batchCount);
|
|
|
+ orderInfo.setStatus(ORDER_SENT.status());
|
|
|
+ orderInfo.setNote("没有合适的通道,入待发送");
|
|
|
+ orderInfo.setChannelId(changeChannelProduct.getChannelId());
|
|
|
+ orderUpdateService.updateOrder(orderInfo, SENDING_TAG);
|
|
|
+ //更新历史发送记录
|
|
|
+ Map<Long, Integer> thisLog = recordLog.get(batchCount);
|
|
|
+ if (thisLog == null) {
|
|
|
+ thisLog = new HashMap<>();
|
|
|
+ }
|
|
|
+ thisLog.put(changeChannelProduct.getChannelId(), 1);
|
|
|
+ recordLog.put(batchCount, thisLog);
|
|
|
+ String logStr = null;
|
|
|
+ try {
|
|
|
+ logStr = om.writeValueAsString(thisLog);
|
|
|
+ } catch (JsonProcessingException e) {
|
|
|
+ log.error("存储分发记录中,分发日志转换时异常", e);
|
|
|
+ }
|
|
|
+ MobileFlowDispatchRec newChildOrder = MobileFlowDispatchRec.builder()
|
|
|
+ .orderId(orderId)
|
|
|
+ .recId(orderId + nowSendCount)
|
|
|
+ .batchCount(batchCount)
|
|
|
+ .phoneNo(orderInfo.getPhoneNo())
|
|
|
+ .packageId(changeChannelProduct.getPackageId())
|
|
|
+ .flowAmount(changeChannelProduct.getFacePrice())
|
|
|
+ .createDate(new Date())
|
|
|
+ .sendStatus(ORDER_SENT.status())
|
|
|
+ .phoneHome(orderInfo.getPhoneHome())
|
|
|
+ .appId(orderInfo.getAppId())
|
|
|
+ .operatorBalancePrice(changeChannelProduct.getPrice())
|
|
|
+ .batchCount(batchCount)
|
|
|
+ .sendCount(nowSendCount)
|
|
|
+ .customerProductsId(orderInfo.getCustomerProductId())
|
|
|
+ .customerName(orderInfo.getCustomerName())
|
|
|
+ .channelProductsId(changeChannelProduct.getChannelProductId())
|
|
|
+ .recordLog(logStr)
|
|
|
+ .channelName(changeChannelProduct.getChannelInfo().getChannelName())
|
|
|
+ .phoneOperator(orderInfo.getPhoneOperator())
|
|
|
+ .build();
|
|
|
+ //分发记录入redis,并且发送消息,后面入db和es
|
|
|
+ orderUpdateService.updateChildOrder(newChildOrder, MAKE_TAG);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|