Authored by LUOXC

Merge branch 'hotfix-20191028' into test6.9.14

# Conflicts:
#	promotion/src/main/java/com/yohoufo/promotion/service/impl/CouponServiceImpl.java
... ... @@ -2,6 +2,7 @@ package com.yohoufo.promotion.service.impl;
import com.google.common.collect.Lists;
import com.google.common.collect.Range;
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
import com.yoho.error.ServiceError;
import com.yoho.error.exception.ServiceException;
import com.yohobuy.ufo.model.promotion.UserCouponsBo;
... ... @@ -14,6 +15,9 @@ import com.yohobuy.ufo.model.promotion.request.UserCouponListReq;
import com.yohobuy.ufo.model.promotion.response.CouponInfo;
import com.yohobuy.ufo.model.promotion.response.CouponInfoListBo;
import com.yohobuy.ufo.model.promotion.response.CouponSendBo;
import com.yohoufo.common.exception.UfoServiceException;
import com.yohoufo.common.lock.RedisLock;
import com.yohoufo.common.lock.RedisLockFactory;
import com.yohoufo.common.utils.DateUtil;
import com.yohoufo.dal.promotion.CouponMapper;
import com.yohoufo.dal.promotion.UserCouponMapper;
... ... @@ -32,6 +36,7 @@ import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
... ... @@ -53,6 +58,9 @@ public class CouponServiceImpl implements ICouponService {
@Autowired
SingleCentCouponService singleCentSyncCoupNumService;
@Autowired
private RedisLockFactory redisLockFactory;
private final Logger logger = LoggerFactory.getLogger(getClass());
... ... @@ -202,6 +210,7 @@ public class CouponServiceImpl implements ICouponService {
logger.warn("sendCoupon query coupon info,coupontype is null:{}", couponToken);
throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_NOT_EXISTS);
}
Coupon coupon = couponAndType.getCoupon();
//check receive start time
if(receiveStartTimeChkNecessary){
... ... @@ -211,7 +220,7 @@ public class CouponServiceImpl implements ICouponService {
if(!repeatable){
// 校验是否可以领取(重复领取,时间是否合法,状态)
checkCanAcquire(uid, couponToken, couponAndType);
redisLock = checkCanAcquire(uid, couponToken, couponAndType);
}
if (coupon.getStatus() != CouponsStatusEnum.VALID.getCode()){
... ... @@ -235,19 +244,16 @@ public class CouponServiceImpl implements ICouponService {
}
int count = 0;
// 不可重复
if (!repeatable){
count = userCouponMapper.insertWhere(userCoupon);
}else{
count = userCouponMapper.insert(userCoupon);
}
count = userCouponMapper.insert(userCoupon);
if (count == 0){
logger.info("can not repeatable acquire coupon. uid is {}, coupon is {}", uid, couponToken);
throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_RECEIVED);
}
logger.info("senCoupon success,{},{},{},{}", uid, couponToken, couponCode, count);
if(Objects.nonNull(redisLock)){
redisLock.unlock();
}
return couponCode;
}
... ... @@ -344,13 +350,22 @@ public class CouponServiceImpl implements ICouponService {
}
private void checkCanAcquire(Integer uid, String couponToken, CouponAndType couponAndType) {
private RedisLock checkCanAcquire(Integer uid, String couponToken, CouponAndType couponAndType) {
// 验证该用户是否重复领取
UserCoupon userCoupon = userCouponMapper.selectByUidAndToken(uid, couponToken);
RedisLock redisLock = redisLockFactory.newLock(RedisKeyBuilder.newInstance()
.appendFixed("ufo:promotion:coupons:checkCanAcquire:")
.appendVar(uid + "-" + couponToken), 3, TimeUnit.SECONDS);
if (!redisLock.tryLock()) {
logger.info("{} checkCanAcquire fail, it already in the process", uid);
throw new UfoServiceException(400, "优惠券领取中");
}
if (userCoupon != null){
logger.warn("user has acquried this coupon before:{},{}", uid, couponToken);
throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_RECEIVED);
}
return redisLock;
}
... ...