Authored by LUOXC

fixbug

@@ -2,6 +2,7 @@ package com.yohoufo.promotion.service.impl; @@ -2,6 +2,7 @@ package com.yohoufo.promotion.service.impl;
2 2
3 import com.google.common.collect.Lists; 3 import com.google.common.collect.Lists;
4 import com.google.common.collect.Range; 4 import com.google.common.collect.Range;
  5 +import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
5 import com.yoho.error.ServiceError; 6 import com.yoho.error.ServiceError;
6 import com.yoho.error.exception.ServiceException; 7 import com.yoho.error.exception.ServiceException;
7 import com.yohobuy.ufo.model.promotion.UserCouponsBo; 8 import com.yohobuy.ufo.model.promotion.UserCouponsBo;
@@ -14,6 +15,9 @@ import com.yohobuy.ufo.model.promotion.request.UserCouponListReq; @@ -14,6 +15,9 @@ import com.yohobuy.ufo.model.promotion.request.UserCouponListReq;
14 import com.yohobuy.ufo.model.promotion.response.CouponInfo; 15 import com.yohobuy.ufo.model.promotion.response.CouponInfo;
15 import com.yohobuy.ufo.model.promotion.response.CouponInfoListBo; 16 import com.yohobuy.ufo.model.promotion.response.CouponInfoListBo;
16 import com.yohobuy.ufo.model.promotion.response.CouponSendBo; 17 import com.yohobuy.ufo.model.promotion.response.CouponSendBo;
  18 +import com.yohoufo.common.exception.UfoServiceException;
  19 +import com.yohoufo.common.lock.RedisLock;
  20 +import com.yohoufo.common.lock.RedisLockFactory;
17 import com.yohoufo.common.utils.DateUtil; 21 import com.yohoufo.common.utils.DateUtil;
18 import com.yohoufo.dal.promotion.CouponMapper; 22 import com.yohoufo.dal.promotion.CouponMapper;
19 import com.yohoufo.dal.promotion.UserCouponMapper; 23 import com.yohoufo.dal.promotion.UserCouponMapper;
@@ -32,6 +36,7 @@ import java.time.LocalDateTime; @@ -32,6 +36,7 @@ import java.time.LocalDateTime;
32 import java.time.LocalTime; 36 import java.time.LocalTime;
33 import java.time.ZoneOffset; 37 import java.time.ZoneOffset;
34 import java.util.*; 38 import java.util.*;
  39 +import java.util.concurrent.TimeUnit;
35 import java.util.function.Function; 40 import java.util.function.Function;
36 import java.util.stream.Collectors; 41 import java.util.stream.Collectors;
37 42
@@ -53,6 +58,9 @@ public class CouponServiceImpl implements ICouponService { @@ -53,6 +58,9 @@ public class CouponServiceImpl implements ICouponService {
53 @Autowired 58 @Autowired
54 SingleCentCouponService singleCentSyncCoupNumService; 59 SingleCentCouponService singleCentSyncCoupNumService;
55 60
  61 + @Autowired
  62 + private RedisLockFactory redisLockFactory;
  63 +
56 64
57 private final Logger logger = LoggerFactory.getLogger(getClass()); 65 private final Logger logger = LoggerFactory.getLogger(getClass());
58 66
@@ -181,10 +189,10 @@ public class CouponServiceImpl implements ICouponService { @@ -181,10 +189,10 @@ public class CouponServiceImpl implements ICouponService {
181 logger.warn("query coupon info,coupontype is null:{}", couponToken); 189 logger.warn("query coupon info,coupontype is null:{}", couponToken);
182 throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_NOT_EXISTS); 190 throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_NOT_EXISTS);
183 } 191 }
184 - 192 + RedisLock redisLock = null;
185 if(!repeatable){ 193 if(!repeatable){
186 // 校验是否可以领取(重复领取,时间是否合法,状态) 194 // 校验是否可以领取(重复领取,时间是否合法,状态)
187 - checkCanAcquire(uid, couponToken, couponAndType); 195 + redisLock = checkCanAcquire(uid, couponToken, couponAndType);
188 } 196 }
189 197
190 if (couponAndType.getCoupon().getStatus() != CouponsStatusEnum.VALID.getCode()){ 198 if (couponAndType.getCoupon().getStatus() != CouponsStatusEnum.VALID.getCode()){
@@ -208,19 +216,16 @@ public class CouponServiceImpl implements ICouponService { @@ -208,19 +216,16 @@ public class CouponServiceImpl implements ICouponService {
208 } 216 }
209 217
210 int count = 0; 218 int count = 0;
211 - // 不可重复  
212 - if (!repeatable){  
213 - count = userCouponMapper.insertWhere(userCoupon);  
214 - }else{  
215 count = userCouponMapper.insert(userCoupon); 219 count = userCouponMapper.insert(userCoupon);
216 - }  
217 -  
218 if (count == 0){ 220 if (count == 0){
219 logger.info("can not repeatable acquire coupon. uid is {}, coupon is {}", uid, couponToken); 221 logger.info("can not repeatable acquire coupon. uid is {}, coupon is {}", uid, couponToken);
220 throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_RECEIVED); 222 throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_RECEIVED);
221 } 223 }
222 224
223 logger.info("senCoupon success,{},{},{},{}", uid, couponToken, couponCode, count); 225 logger.info("senCoupon success,{},{},{},{}", uid, couponToken, couponCode, count);
  226 + if(Objects.nonNull(redisLock)){
  227 + redisLock.unlock();
  228 + }
224 return couponCode; 229 return couponCode;
225 } 230 }
226 231
@@ -317,13 +322,22 @@ public class CouponServiceImpl implements ICouponService { @@ -317,13 +322,22 @@ public class CouponServiceImpl implements ICouponService {
317 } 322 }
318 323
319 324
320 - private void checkCanAcquire(Integer uid, String couponToken, CouponAndType couponAndType) { 325 + private RedisLock checkCanAcquire(Integer uid, String couponToken, CouponAndType couponAndType) {
321 // 验证该用户是否重复领取 326 // 验证该用户是否重复领取
322 UserCoupon userCoupon = userCouponMapper.selectByUidAndToken(uid, couponToken); 327 UserCoupon userCoupon = userCouponMapper.selectByUidAndToken(uid, couponToken);
  328 +
  329 + RedisLock redisLock = redisLockFactory.newLock(RedisKeyBuilder.newInstance()
  330 + .appendFixed("ufo:promotion:coupons:checkCanAcquire:")
  331 + .appendVar(uid + "-" + couponToken), 3, TimeUnit.SECONDS);
  332 + if (!redisLock.tryLock()) {
  333 + logger.info("{} checkCanAcquire fail, it already in the process", uid);
  334 + throw new UfoServiceException(400, "优惠券领取中");
  335 + }
323 if (userCoupon != null){ 336 if (userCoupon != null){
324 logger.warn("user has acquried this coupon before:{},{}", uid, couponToken); 337 logger.warn("user has acquried this coupon before:{},{}", uid, couponToken);
325 throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_RECEIVED); 338 throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_RECEIVED);
326 } 339 }
  340 + return redisLock;
327 341
328 } 342 }
329 343