refactor(market):优化代码结构
This commit is contained in:
@@ -1,30 +1,14 @@
|
||||
package com.jzo2o.market.handler;
|
||||
|
||||
import com.jzo2o.common.expcetions.DBException;
|
||||
import com.jzo2o.common.utils.BeanUtils;
|
||||
import com.jzo2o.common.utils.CollUtils;
|
||||
import com.jzo2o.common.utils.JsonUtils;
|
||||
import com.jzo2o.market.constants.RedisConstants;
|
||||
import com.jzo2o.market.enums.ActivityStatusEnum;
|
||||
import com.jzo2o.market.enums.CouponStatusEnum;
|
||||
import com.jzo2o.market.model.domain.Activity;
|
||||
import com.jzo2o.market.model.domain.Coupon;
|
||||
import com.jzo2o.market.model.dto.response.SeizeCouponInfoResDTO;
|
||||
import com.jzo2o.market.service.IActivityService;
|
||||
import com.jzo2o.market.service.ICouponService;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.HashOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* XxlJob任务处理器
|
||||
@@ -50,65 +34,18 @@ public class XxlJobHandler {
|
||||
@Transactional
|
||||
public void updateActivityStatus() {
|
||||
log.info("自动修改活动状态任务开始");
|
||||
LocalDateTime nowTime = LocalDateTime.now();
|
||||
List<Activity> activityList = activityService.lambdaQuery()
|
||||
.eq(Activity::getStatus, ActivityStatusEnum.NO_DISTRIBUTE)
|
||||
.or().eq(Activity::getStatus, ActivityStatusEnum.DISTRIBUTING)
|
||||
// 不处理还没有发生的活动
|
||||
.le(Activity::getDistributeStartTime, nowTime)
|
||||
.list();
|
||||
|
||||
if (CollUtils.isEmpty(activityList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Activity activity : activityList) {
|
||||
if (activity.getDistributeEndTime().isBefore(nowTime)) {
|
||||
// 活动结束
|
||||
if (!activityService.lambdaUpdate()
|
||||
.eq(Activity::getId, activity.getId())
|
||||
.set(Activity::getStatus, ActivityStatusEnum.LOSE_EFFICACY)
|
||||
.update()) {
|
||||
throw new DBException("更新活动状态失败");
|
||||
}
|
||||
} else if (activity.getDistributeStartTime().isBefore(nowTime)) {
|
||||
// 活动开始
|
||||
if (!activityService.lambdaUpdate()
|
||||
.eq(Activity::getId, activity.getId())
|
||||
.set(Activity::getStatus, ActivityStatusEnum.DISTRIBUTING)
|
||||
.update()) {
|
||||
throw new DBException("更新活动状态失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
activityService.updateActivityStatus();
|
||||
log.info("自动修改活动状态任务完成");
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动过期已领取优惠券(1小时1次)
|
||||
*/
|
||||
@XxlJob("processExpireCoupon")
|
||||
@Transactional
|
||||
public void processExpireCoupon() {
|
||||
log.info("自动过期已领取优惠券任务开始");
|
||||
List<Coupon> couponList = couponService.lambdaQuery()
|
||||
.eq(Coupon::getStatus, CouponStatusEnum.NO_USE)
|
||||
// 不处理还没到有效期的优惠卷
|
||||
.le(Coupon::getValidityTime, LocalDateTime.now())
|
||||
.select(Coupon::getId)
|
||||
.list();
|
||||
|
||||
if (CollUtils.isEmpty(couponList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置状态已失效
|
||||
couponList = couponList.stream()
|
||||
.map(coupon -> coupon.setStatus(CouponStatusEnum.INVALID))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!couponService.updateBatchById(couponList)) {
|
||||
throw new DBException("更新优惠卷状态失败");
|
||||
}
|
||||
couponService.invalidExpiredCoupon();
|
||||
log.info("自动过期已领取优惠券任务完成");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,43 +54,7 @@ public class XxlJobHandler {
|
||||
@XxlJob("activityPreheat")
|
||||
public void activityPreheat() {
|
||||
log.info("自动预热1个月内的活动任务开始");
|
||||
LocalDateTime nowTime = LocalDateTime.now();
|
||||
|
||||
// 获取近一个月未开始/已开始的活动
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Activity> activityList = activityService.lambdaQuery()
|
||||
.le(Activity::getDistributeStartTime, nowTime.plusDays(30))
|
||||
.in(Activity::getStatus, Arrays.asList(ActivityStatusEnum.NO_DISTRIBUTE, ActivityStatusEnum.DISTRIBUTING))
|
||||
.orderByAsc(Activity::getDistributeStartTime)
|
||||
.list();
|
||||
|
||||
if (CollUtils.isEmpty(activityList)) {
|
||||
activityList = new ArrayList<>();
|
||||
}
|
||||
|
||||
List<SeizeCouponInfoResDTO> couponInfoList = activityList.stream()
|
||||
.map(activity -> BeanUtils
|
||||
.toBean(activity, SeizeCouponInfoResDTO.class)
|
||||
.setRemainNum(activity.getStockNum())
|
||||
.setType(activity.getType().getType()))
|
||||
.collect(Collectors.toList());
|
||||
String couponInfoListJsonStr = JsonUtils.toJsonStr(couponInfoList);
|
||||
|
||||
// 缓存活动列表
|
||||
redisTemplate
|
||||
.opsForValue()
|
||||
.set(RedisConstants.RedisKey.ACTIVITY_CACHE_LIST, couponInfoListJsonStr);
|
||||
|
||||
// 缓存优惠卷库存
|
||||
HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
|
||||
couponInfoList.forEach(coupon -> {
|
||||
String key = String.format(RedisConstants.RedisKey.COUPON_RESOURCE_STOCK, coupon.getId() % 10);
|
||||
// 防止进行中的活动的库存被覆盖
|
||||
if (coupon.getStatus() == ActivityStatusEnum.NO_DISTRIBUTE) {
|
||||
hashOperations.put(key, coupon.getId(), coupon.getRemainNum());
|
||||
} else {
|
||||
hashOperations.putIfAbsent(key, coupon.getId(), coupon.getRemainNum());
|
||||
}
|
||||
});
|
||||
activityService.cacheComingActivity();
|
||||
log.info("自动预热1个月内的活动任务完成");
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,16 @@ public interface IActivityService extends IService<Activity> {
|
||||
*/
|
||||
void revoke(Long id);
|
||||
|
||||
/**
|
||||
* 根据当前时间更新活动状态
|
||||
*/
|
||||
void updateActivityStatus();
|
||||
|
||||
/**
|
||||
* 缓存近1个月生效的活动信息
|
||||
*/
|
||||
void cacheComingActivity();
|
||||
|
||||
/**
|
||||
* 用户端进行抢卷操作
|
||||
*/
|
||||
|
||||
@@ -28,4 +28,9 @@ public interface ICouponService extends IService<Coupon> {
|
||||
* 用户端滚动查询(抢卷时间降序)
|
||||
*/
|
||||
List<CouponSimpleInfoResDTO> getCurrentUserCoupon(CouponStatusEnum status, Integer lastId);
|
||||
|
||||
/**
|
||||
* 更新过期优惠卷的状态为失效中
|
||||
*/
|
||||
void invalidExpiredCoupon();
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import com.jzo2o.common.model.PageResult;
|
||||
import com.jzo2o.common.utils.BeanUtils;
|
||||
import com.jzo2o.common.utils.CollUtils;
|
||||
import com.jzo2o.common.utils.JsonUtils;
|
||||
import com.jzo2o.market.constants.RedisConstants;
|
||||
import com.jzo2o.market.enums.ActivityStatusEnum;
|
||||
import com.jzo2o.market.enums.CouponStatusEnum;
|
||||
import com.jzo2o.market.enums.CouponTypeEnum;
|
||||
@@ -29,7 +30,9 @@ import com.jzo2o.market.service.IActivityService;
|
||||
import com.jzo2o.market.service.ICouponService;
|
||||
import com.jzo2o.mvc.utils.UserContext;
|
||||
import com.jzo2o.mysql.utils.PageUtils;
|
||||
import com.jzo2o.redis.properties.RedisSyncProperties;
|
||||
import com.jzo2o.redis.utils.RedisSyncQueueUtils;
|
||||
import org.springframework.data.redis.core.HashOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.script.RedisScript;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -178,6 +181,79 @@ public class ActivityServiceImpl extends ServiceImpl<ActivityMapper, Activity> i
|
||||
.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateActivityStatus() {
|
||||
LocalDateTime nowTime = LocalDateTime.now();
|
||||
List<Activity> activityList = lambdaQuery()
|
||||
.in(Activity::getStatus, ActivityStatusEnum.NO_DISTRIBUTE, ActivityStatusEnum.DISTRIBUTING)
|
||||
// 不处理还没有发生的活动
|
||||
.le(Activity::getDistributeStartTime, nowTime)
|
||||
.list();
|
||||
|
||||
if (CollUtils.isEmpty(activityList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Activity activity : activityList) {
|
||||
ActivityStatusEnum status;
|
||||
if (activity.getDistributeEndTime().isBefore(nowTime)) {
|
||||
// 活动结束
|
||||
status = ActivityStatusEnum.LOSE_EFFICACY;
|
||||
} else if (activity.getDistributeStartTime().isBefore(nowTime)) {
|
||||
// 活动开始
|
||||
status = ActivityStatusEnum.DISTRIBUTING;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!lambdaUpdate()
|
||||
.eq(Activity::getId, activity.getId())
|
||||
.set(Activity::getStatus, status)
|
||||
.update()) {
|
||||
throw new DBException("更新活动状态失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cacheComingActivity() {
|
||||
LocalDateTime nowTime = LocalDateTime.now();
|
||||
|
||||
// 获取近一个月未开始/已开始的活动
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Activity> activityList = lambdaQuery()
|
||||
.le(Activity::getDistributeStartTime, nowTime.plusDays(30))
|
||||
.in(Activity::getStatus, Arrays.asList(ActivityStatusEnum.NO_DISTRIBUTE, ActivityStatusEnum.DISTRIBUTING))
|
||||
.orderByAsc(Activity::getDistributeStartTime)
|
||||
.list();
|
||||
|
||||
if (CollUtils.isEmpty(activityList)) {
|
||||
activityList = new ArrayList<>();
|
||||
}
|
||||
|
||||
List<SeizeCouponInfoResDTO> couponInfoList = activityList.stream()
|
||||
.map(activity -> BeanUtils
|
||||
.toBean(activity, SeizeCouponInfoResDTO.class)
|
||||
.setRemainNum(activity.getStockNum())
|
||||
.setType(activity.getType().getType()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 缓存活动列表
|
||||
redisTemplate.opsForValue().set(RedisConstants.RedisKey.ACTIVITY_CACHE_LIST, JsonUtils.toJsonStr(couponInfoList));
|
||||
|
||||
// 缓存优惠卷库存
|
||||
HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
|
||||
couponInfoList.forEach(coupon -> {
|
||||
String key = String.format(RedisConstants.RedisKey.COUPON_RESOURCE_STOCK, coupon.getId() % redisSyncProperties.getQueueNum());
|
||||
// 防止进行中的活动的库存被覆盖
|
||||
if (coupon.getStatus() == ActivityStatusEnum.NO_DISTRIBUTE) {
|
||||
hashOperations.put(key, coupon.getId(), coupon.getRemainNum());
|
||||
} else {
|
||||
hashOperations.putIfAbsent(key, coupon.getId(), coupon.getRemainNum());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seizeCoupon(SeizeCouponReqDTO seizeCouponReqDTO) {
|
||||
Long activityId = seizeCouponReqDTO.getId();
|
||||
|
||||
@@ -5,7 +5,9 @@ import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.jzo2o.api.customer.CommonUserApi;
|
||||
import com.jzo2o.common.expcetions.BadRequestException;
|
||||
import com.jzo2o.common.expcetions.DBException;
|
||||
import com.jzo2o.common.model.PageResult;
|
||||
import com.jzo2o.common.utils.BeanUtils;
|
||||
import com.jzo2o.common.utils.CollUtils;
|
||||
@@ -15,12 +17,18 @@ import com.jzo2o.market.model.domain.Coupon;
|
||||
import com.jzo2o.market.model.dto.request.CouponPageQueryDTO;
|
||||
import com.jzo2o.market.model.dto.response.CouponPageInfoResDTO;
|
||||
import com.jzo2o.market.model.dto.response.CouponSimpleInfoResDTO;
|
||||
import com.jzo2o.market.service.IActivityService;
|
||||
import com.jzo2o.market.service.ICouponService;
|
||||
import com.jzo2o.mvc.utils.UserContext;
|
||||
import com.jzo2o.mysql.utils.PageUtils;
|
||||
import com.jzo2o.redis.properties.RedisSyncProperties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -35,6 +43,15 @@ import java.util.stream.Collectors;
|
||||
@Service
|
||||
@Slf4j
|
||||
public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements ICouponService {
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
@Resource
|
||||
private RedisSyncProperties redisSyncProperties;
|
||||
@Resource
|
||||
private CommonUserApi commonUserApi;
|
||||
@Resource
|
||||
private IActivityService activityService;
|
||||
|
||||
@Override
|
||||
public PageResult<CouponPageInfoResDTO> page(CouponPageQueryDTO couponPageQueryDTO) {
|
||||
if (ObjectUtils.isEmpty(couponPageQueryDTO.getActivityId())) {
|
||||
@@ -69,4 +86,28 @@ public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> impleme
|
||||
.map(coupon -> BeanUtils.toBean(coupon, CouponSimpleInfoResDTO.class))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void invalidExpiredCoupon() {
|
||||
List<Coupon> couponList = lambdaQuery()
|
||||
.eq(Coupon::getStatus, CouponStatusEnum.NO_USE)
|
||||
// 不处理还没到有效期的优惠卷
|
||||
.le(Coupon::getValidityTime, LocalDateTime.now())
|
||||
.select(Coupon::getId)
|
||||
.list();
|
||||
|
||||
if (CollUtils.isEmpty(couponList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置状态已失效
|
||||
couponList = couponList.stream()
|
||||
.map(coupon -> coupon.setStatus(CouponStatusEnum.INVALID))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!this.updateBatchById(couponList)) {
|
||||
throw new DBException("更新优惠卷状态失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user