Authored by chenchao

add bonded order trace info

package com.yoho.core.rabbitmq.properties;
import com.google.common.base.Splitter;
import lombok.Getter;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.YamlMapFactoryBean;
import org.springframework.core.io.ClassPathResource;
import java.util.*;
import java.util.stream.Collectors;
/**
* Created by jack on 2017/10/11.
* <p>
* for read rabbitmq.yml
*/
public class RabbitYmlFactory {
private static final Logger logger = LoggerFactory.getLogger(RabbitYmlFactory.class);
// consumer info list
@Getter
private static List<ConsumerInfo> consumerInfoList = new ArrayList<>();
//producer info list
@Getter
private static List<ProducerInfo> producerInfoList = new ArrayList<>();
//connection info list
@Getter
private static HashSet<ConnectionInfo> connectionInfoSet = new HashSet<>();
// web context
private static String webContext;
//class load read yaml
static {
readRabbitYml();
}
public static void readRabbitYml() throws BeansException {
YamlMapFactoryBean yaml = new YamlMapFactoryBean();
ClassPathResource oneResource = new ClassPathResource("rabbitmq.yml");
if (!oneResource.exists()) {
logger.error("not found rabbitmq.yml in classpath...");
return;
}
yaml.setResources(oneResource);
Map<String, Object> rabbitmqYml = yaml.getObject();
try {
Configuration configuration = new PropertiesConfiguration(RabbitYmlFactory.class.getClassLoader().getResource("config.properties"));
if (null != configuration) {
webContext = Optional.ofNullable(configuration.getString("web.context")).orElse("default");
}
} catch (ConfigurationException e) {
logger.error("not found config.properties in classpath...");
webContext = "default";
}
// read consumers
readConsumers(rabbitmqYml);
//read producers
readProducers(rabbitmqYml);
}
private static final int DEFAULT_DELAY_INTERVAL = 10;
private static final String SEPERATOR = ",";
private static Set<Integer> buildDelayIntervalSet(Map<String, Object> consumerMap){
Set<Integer> delayIntervalSet = new HashSet<>(8);
Map<String, Object> delay = (Map<String, Object>) consumerMap.get("delay");
if (Objects.isNull(delay)){
delayIntervalSet.add(DEFAULT_DELAY_INTERVAL);
return delayIntervalSet;
}
//parse interval
String intervalStr = String.valueOf(delay.get("interval"));
if (StringUtils.isBlank(intervalStr)){
delayIntervalSet.add(DEFAULT_DELAY_INTERVAL);
return delayIntervalSet;
}
if(intervalStr.contains(SEPERATOR)){
List<String> delayIntervalStrList = Splitter.on(SEPERATOR)
.omitEmptyStrings().trimResults()
.splitToList(intervalStr);
//multiple
delayIntervalSet = delayIntervalStrList
.stream().map(Integer::valueOf)
.collect(Collectors.toSet());
}else {
//single
Integer delayInterval = Optional.ofNullable(Integer.valueOf(intervalStr)).orElse(10);
delayIntervalSet.add(delayInterval);
}
return delayIntervalSet;
}
/**
* read consumers defined in rabbitmq.yml
*
* @param rabbitmqYml
* @throws Exception
*/
private static void readConsumers(Map<String, Object> rabbitmqYml) throws BeansException {
logger.info("RabbitYmlFactory:read consumers");
List<Object> connections = (List<Object>) rabbitmqYml.get("consumer");
if (null == connections) return;
for (Object oneConn : connections) {
Map<String, Object> connMap = (Map<String, Object>) oneConn;
List<Object> consumerList = (List<Object>) connMap.get("consumers");
//if no consumers are in this connection , continue
if (null == consumerList) continue;
// construct connection info
String address = (String) connMap.get("address");
String user = Optional.ofNullable((String) connMap.get("username")).orElse("yoho");
String passwd = Optional.ofNullable((String) connMap.get("password")).orElse("yoho");
String vhost = Optional.ofNullable((String) connMap.get("vhost")).orElse("yoho");
Integer heartbeat = Optional.ofNullable((Integer) connMap.get("hearbeat")).orElse(5);
ConnectionInfo consumerConn = new ConnectionInfo(address, user, passwd, vhost, heartbeat);
String connectionBean = "rabbit-connection-" + consumerConn.hashCode();
consumerConn.setBeanId(connectionBean);
connectionInfoSet.add(consumerConn);
//construct consumer info
for (Object oneConsumer : consumerList) {
Map<String, Object> consumerMap = (Map<String, Object>) oneConsumer;
boolean existDelayKey = consumerMap.containsKey("delay");
int sonNum = 1;
Set<Integer> delayIntervalSet = null;
if (existDelayKey){
delayIntervalSet = buildDelayIntervalSet(consumerMap);
sonNum= delayIntervalSet.size();
}
if (sonNum==1){
ConsumerInfo info = buildSingleConsumerInfo(consumerMap, consumerConn, existDelayKey, existDelayKey ? delayIntervalSet.iterator().next():null);
consumerInfoList.add(info);
}else{
delayIntervalSet.stream().forEach(delayInterval-> consumerInfoList.add(buildSingleConsumerInfo(consumerMap,consumerConn, existDelayKey, delayInterval)));
}
}
}
logger.info("RabbitYmlFactory: consumers info {}", consumerInfoList);
}
private static ConsumerInfo buildSingleConsumerInfo(Map<String, Object> consumerMap,
ConnectionInfo consumerConn,
boolean existDelayKey,
Integer delayInterval){
ConsumerInfo info = new ConsumerInfo();
info.setConnection(consumerConn);
info.setConsumeClass((String) consumerMap.get("class"));
info.setTopic((String) consumerMap.get("topic"));
//default yoho:webcontext:topic
String queue = Optional.ofNullable((String) consumerMap.get("queue")).orElse(info.getTopic());
info.setQueue("yoho:" + webContext + ":" + queue);
info.setConcurrent(Optional.ofNullable((Integer) consumerMap.get("concurrent")).orElse(1));
info.setPrefetch(Optional.ofNullable((Integer) consumerMap.get("prefetch")).orElse(10));
//set federation config
if (consumerMap.containsKey("federation")) {
info.setFederation(true);
Map<String, Object> fed = (Map<String, Object>) consumerMap.get("federation");
if (null != fed) {
info.setFedExchange(Optional.ofNullable((String) fed.get("exchange")).orElse("yoho.federation.topic"));
} else {
info.setFedExchange("yoho.federation.topic");
}
}
//if contains retry
if (consumerMap.containsKey("retry")) {
info.setRetry(true);
//default yoho_retry:webcontext:topic
info.setQueue("yoho_retry:" + webContext + ":" + queue);
Map<String, Object> retry = (Map<String, Object>) consumerMap.get("retry");
if (retry != null) {
info.setRetryInterval(Optional.of((Integer) retry.get("interval")).orElse(10));
//default queueName:retry:10m
info.setRetryQueue(Optional.ofNullable((String) retry.get("queue")).orElse("retry:" + info.getRetryInterval() + "m" + ".queue"));
} else {
info.setRetryInterval(10);
info.setRetryQueue("retry:" + info.getRetryInterval() + "m" + ".queue");
}
}
//if contains delay
if (existDelayKey) {
//set first,then get after
info.setDelayInterval(delayInterval);
info.setDelay(true);
info.setQueue("yoho_delay:" + webContext + ":" + queue);
Map<String, Object> delay = (Map<String, Object>) consumerMap.get("delay");
if (null != delay) {
//default delay:10m.queue
info.setDelayQueue(Optional.ofNullable((String) delay.get("queue")).orElse("delay:" + info.getDelayInterval() + "m" + ".queue"));
} else {
info.setDelayQueue("delay:" + info.getDelayInterval() + "m" + ".queue");
}
}
//if contains rateLimit
Integer rate = Optional.ofNullable((Integer) consumerMap.get("ratelimit")).orElse(0);
if (0 < rate) {
info.setRateLimit(true);
info.setRateLimiter(rate);
}
String beanId = "consumer-" + UUID.randomUUID().toString();
info.setBeanName(beanId);
return info;
}
/**
* read producers defined in rabbitmq.yml
*
* @param rabbitmqYml
*/
private static void readProducers(Map<String, Object> rabbitmqYml) {
logger.info("RabbitYmlFactory:read producers");
List<Object> allProducers = (List<Object>) rabbitmqYml.get("producer");
if (null == allProducers) {
logger.info("not found producers config in rabbitmq.yml");
return;
}
for (Object oneConn : allProducers) {
Map<String, Object> connMap = (Map<String, Object>) oneConn;
List<Object> producers = (List<Object>) connMap.get("producers");
if (null == producers) continue;
// construct connection info
String address = (String) connMap.get("address");
String user = Optional.ofNullable((String) connMap.get("username")).orElse("yoho");
String passwd = Optional.ofNullable((String) connMap.get("password")).orElse("yoho");
String vhost = Optional.ofNullable((String) connMap.get("vhost")).orElse("yoho");
Integer heartbeat = Optional.ofNullable((Integer) connMap.get("hearbeat")).orElse(5);
ConnectionInfo producerConn = new ConnectionInfo(address, user, passwd, vhost, heartbeat);
String connectionBean = "rabbit-connection-" + producerConn.hashCode();
producerConn.setBeanId(connectionBean);
connectionInfoSet.add(producerConn);
//construct producer info
for (Object oneProducer : producers) {
Map<String, Object> producerMap = (Map<String, Object>) oneProducer;
ProducerInfo info = new ProducerInfo();
info.setConnection(producerConn);
info.setAsync(Optional.ofNullable((Boolean) producerMap.get("async")).orElse(false));
info.setConfirm(Optional.ofNullable((Boolean) producerMap.get("confirm")).orElse(true));
info.setConfirmCallback(Optional.ofNullable((String)producerMap.get("confirmcallback")).orElse(""));
info.setTrace(Optional.ofNullable((Boolean) producerMap.get("trace")).orElse(false));
info.setPersistent(Optional.ofNullable((Boolean) producerMap.get("persistent")).orElse(false));
String beanId = Optional.ofNullable((String) producerMap.get("bean")).orElse("producer-" + UUID.randomUUID().toString());
info.setBeanName(beanId);
producerInfoList.add(info);
}
}
logger.info("RabbitYmlFactory: producers info {}", producerInfoList);
}
}
... ...
package com.yohoufo.order.model.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.concurrent.TimeUnit;
@Data
@Builder
@NoArgsConstructor@AllArgsConstructor
public class LimitTime {
private int limitTime;
@Builder.Default
private TimeUnit timeUnit = TimeUnit.HOURS;
}
... ...
... ... @@ -292,7 +292,7 @@ public class BuyerOrderPaymentService extends AbstractOrderPaymentService {
Integer sellerUid = orderInfo.getSellerUid();
long orderCode = orderInfo.getOrderCode();
int ts = DateUtil.getCurrentTimeSecond();
int deliveryHours = deliveryMinutesService.getDeliverMinutesThird_hours(ts);//把分钟转小时
int deliveryHours = deliveryMinutesService.getDeliverHoursOfLimitTime(ts, sellerOrderGoods);//把分钟转小时
String unit = DateUtil.UNIT_HOURS;
sellerNoticeFacade.sellerSkupPaidByBuyer(sellerOrderGoods,orderCode,deliveryHours, unit);
... ...
... ... @@ -107,6 +107,8 @@ public class CacheKeyBuilder {
ORDER_PAY_DETAIL("ufo:order:orderPayDetail:", "uid:{}:tabType:{}:orderCode:{}"),
BUYER_ORDER_VIOLATION_PENALTY("ufo:order:buyerOrder:violationPenalty:config",""),
SELLER_DELIVER_LIMIT_TIME("ufo:order:seller:deliver:limitTime","")
;
private String fix;
... ...
... ... @@ -38,17 +38,21 @@ public class SellerCancelDeliverHandler implements IEventHandler<SellerCancelDel
public void handle(SellerCancelDeliverEvent event) {
int ts = DateUtil.getCurrentTimeSecond();
int minutes = 0;
//香港仓-海外购订单
if (event.getOrderAttributes() == OrderAttributes.OVERSEAS_IN_STOCK.getCode()){
minutes = deliveryMinutesService.getDeliverOverSeasMinutes();
}else{
minutes = deliveryMinutesService.getDeliverMinutesThird(ts);
//除了海外购订单,其他所有(现货 二手 瑕疵)
minutes = deliveryMinutesService.getDeliverMinutesThird(ts,event.getSellerOrderGoods());
}
String topic = TopicConstants.SELLER_ORDER_AUTO_CANCEL_DELIVER;
logger.info("Subscribe Buyer Confirm delay msg,topic {}, delay minutes {} , event {}",topic,minutes, event);
tradeMqSender.send(topic, event, minutes);
try{
tradeMqSender.send(topic, event, minutes);
}catch (Exception ex){
logger.warn("SellerCancelDeliverHandler.handle send MQ msg fail,event {} topic {}", event, topic, ex);
}
// 记录此订单的发货超时时间期限点
orderOverTimeService.insertDeliveryTime(new OrderOverTime(event.getOrderCode(), ts + minutes * 60, minutes));
... ...
... ... @@ -23,6 +23,7 @@ public class SellerEarnestMoney2BuyerPenaltyCalculator implements PenaltyCalcula
private final Integer uid;
private final Integer skup;
private final JSONObject fee;
@Setter
@Accessors(fluent = true)
... ...
... ... @@ -469,6 +469,7 @@ public class MetaConfigService {
MetaCodeCacheKeyMap.put(MetaConfigKey.BUYER_BID_CONFIG, CacheKeyBuilder.KeyTemp.BUYER_BID_CONFIG);
MetaCodeCacheKeyMap.put(MetaConfigKey.SELLER_BID_GOODS_FEE_RATE, CacheKeyBuilder.KeyTemp.SELLER_BID_GOODS_FEE_RATE);
MetaCodeCacheKeyMap.put(MetaConfigKey.BUYER_ORDER_VIOLATION_PENALTY, CacheKeyBuilder.KeyTemp.BUYER_ORDER_VIOLATION_PENALTY);
MetaCodeCacheKeyMap.put(MetaConfigKey.SELLER_DELIVER_LIMIT_TIME, CacheKeyBuilder.KeyTemp.SELLER_DELIVER_LIMIT_TIME);
}
}
... ... @@ -480,4 +481,19 @@ public class MetaConfigService {
protected static Map<String,CacheKeyBuilder.KeyTemp> findMetaCodeCacheKeyMap(){
return DataHold.MetaCodeCacheKeyMap;
}
public Map<String,LimitTime> getSellerDeliverLimitTimeConfig(){
final String key = MetaConfigKey.SELLER_DELIVER_LIMIT_TIME;
CacheKeyBuilder.KeyTemp kt = findMetaCodeCacheKeyMap().get(key);
RedisKeyBuilder rkb = kt.builderKeyOnlyFixed();
String configVal = new DataProcesser(rkb, key, ExpiredTime.ORDER_BASE_CONFIG).getConfigVal();
Map<String,LimitTime> ltMap = new HashMap<String,LimitTime>(10);
try{
ltMap = JSONObject.parseObject(configVal, new TypeReference<Map<String,LimitTime>>(){});
}catch (Exception ex){
logger.warn("in getSellerDeliverLimitTimeConfig parseObject fail, metaVal {}", configVal, ex);
}
return ltMap;
}
}
... ...
... ... @@ -3,7 +3,12 @@ package com.yohoufo.order.service.proxy;
import com.yoho.core.cache.LocalCache;
import com.yoho.core.config.ConfigReader;
import com.yohobuy.ufo.model.order.bo.IntervalBo;
import com.yohobuy.ufo.model.order.constants.SkupType;
import com.yohoufo.dal.order.model.SellerOrderGoods;
import com.yohoufo.order.model.dto.LimitTime;
import com.yohoufo.order.service.impl.MetaConfigService;
import lombok.Getter;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -11,6 +16,8 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
... ... @@ -62,6 +69,9 @@ public class DeliveryMinutesService {
@Getter
private int totalMinutes = 36*60;
@Autowired
private MetaConfigService metaConfigService;
@PostConstruct
private void init() {
... ... @@ -95,15 +105,26 @@ public class DeliveryMinutesService {
return MINUTES_DELIVERNOTICE_SECOND;
}
public int getDeliverMinutesThird(int ts){
public int getDeliverMinutesThird(int ts, SellerOrderGoods sellerOrderGoods){
Map<String,LimitTime> limitTimeMap = metaConfigService.getSellerDeliverLimitTimeConfig();
SkupType skupType = SkupType.getSkupType(sellerOrderGoods.getAttributes());
LimitTime limitTime = null;
if (MapUtils.isNotEmpty(limitTimeMap)
&& Objects.nonNull(limitTime=limitTimeMap.get(skupType.getLocalCacheKey()))){
return limitTime.getLimitTime();
}
//当前时刻在某个指定的时刻之前时,使用旧的规则
if(ts<getOnlineTime()){
return minutes_deliverNotice_third_old;
}
return minutes_deliverNotice_third;
}
public int getDeliverMinutesThird_hours(int ts){
int minutes = getDeliverMinutesThird(ts);
public int getDeliverHoursOfLimitTime(int ts, SellerOrderGoods sellerOrderGoods){
int minutes = getDeliverMinutesThird(ts, sellerOrderGoods);
return minutes/60 ;
}
... ... @@ -154,6 +175,10 @@ public class DeliveryMinutesService {
return intervalBo;
}
public static void main(String[] args) {
for(int times=1;times<=3;times++) {
int start = 60;
... ...
... ... @@ -25,7 +25,7 @@ public class DeliveryMinutesServiceTest extends BaseWebTest {
@Test
public void testGetDeliverMinutesThird(){
int ts = DateUtil.getCurrentTimeSecond();
int mins = deliveryMinutesService.getDeliverMinutesThird(ts);
int mins = deliveryMinutesService.getDeliverMinutesThird(ts,null);
System.out.println("testGetDeliverMinutesThird -> " + mins);
}
}
... ...
... ... @@ -7,12 +7,7 @@ consumer:
- class: com.yohoufo.order.mq.consumer.BuyerOrderUnpaidReminderDelayMsgConsumer
topic: buyerOrder.unpaidReminder
delay:
interval: 720
- class: com.yohoufo.order.mq.consumer.BuyerOrderUnpaidReminderDelayMsgConsumer
topic: buyerOrder.unpaidReminder
delay:
interval: 1320
interval: 720,1320
- class: com.yohoufo.order.mq.consumer.WaitingPayDepositBuyerOrderAutoCancelDelayMsgConsumer
topic: waitingPayDepositBuyerOrder.autoCancel
... ... @@ -27,37 +22,12 @@ consumer:
- class: com.yohoufo.order.mq.consumer.BuyerOrderAutoCancelDelayNDayMsgConsumer
topic: buyerOrder.autoCancelAfterNDay
delay:
interval: 1440
- class: com.yohoufo.order.mq.consumer.BuyerOrderAutoCancelDelayNDayMsgConsumer
topic: buyerOrder.autoCancelAfterNDay
delay:
interval: 4320
- class: com.yohoufo.order.mq.consumer.BuyerOrderAutoCancelDelayNDayMsgConsumer
topic: buyerOrder.autoCancelAfterNDay
delay:
interval: 10080
- class: com.yohoufo.order.mq.consumer.BuyerOrderAutoCancelDelayNDayMsgConsumer
topic: buyerOrder.autoCancelAfterNDay
delay:
interval: 21600
- class: com.yohoufo.order.mq.consumer.BuyerOrderAutoCancelDelayNDayMsgConsumer
topic: buyerOrder.autoCancelAfterNDay
delay:
interval: 43200
interval: 1440,4320,10080,21600,43200
- class: com.yohoufo.order.mq.consumer.SellerOrderAutoCancelDelayMsgConsumer
topic: sellerOrder.autoCancel
delay:
interval: 15
- class: com.yohoufo.order.mq.consumer.SellerOrderAutoCancelDelayMsgConsumer
topic: sellerOrder.autoCancel
delay:
interval: 2
interval: 2,15
- class: com.yohoufo.order.mq.consumer.BuyerOrderAutoCancelDelayMsgConsumer
topic: buyerOrder.autoCancel
... ... @@ -74,17 +44,11 @@ consumer:
delay:
interval: 1440
#卖家物流揽收情况检查 24小时
#卖家物流揽收情况检查 24小时 48小时
- class: com.yohoufo.order.mq.consumer.BuyerOrderSellerDeliveryCheckMsgConsumer
topic: buyerOrder.sellerDeliveryCheck
delay:
interval: 1440
#卖家物流揽收情况检查 48小时
- class: com.yohoufo.order.mq.consumer.BuyerOrderSellerDeliveryCheckMsgConsumer
topic: buyerOrder.sellerDeliveryCheck
delay:
interval: 2880
interval: 1440,2880
#- class: com.yohoufo.order.mq.consumer.BuyerOrderCancelShamDeliveryMsgConsumer
# topic: buyerOrder.cancelShamDeliver
... ... @@ -99,22 +63,12 @@ consumer:
- class: com.yohoufo.order.mq.consumer.NotDeliverNoticeDelayMsgConsumer
topic: order.notDeliver
delay:
interval: 1440
- class: com.yohoufo.order.mq.consumer.NotDeliverNoticeDelayMsgConsumer
topic: order.notDeliver
delay:
interval: 29520
- class: com.yohoufo.order.mq.consumer.SellerOrderCancelDeliverDelayMsgConsumer
topic: sellerOrder.autoCancelDeliver
delay:
interval: 2160
interval: 1440,29520
- class: com.yohoufo.order.mq.consumer.SellerOrderCancelDeliverDelayMsgConsumer
topic: sellerOrder.autoCancelDeliver
delay:
interval: 30240
interval: 2160,30240
# 平台鉴定不能确定补发优惠券回调
- class: com.yohoufo.order.mq.consumer.BuyerCouponSendResultForAppraiseUnsureConsumer
... ...