通过延时队列实现检查订单是否已经超期,自动取消订单的功能
This commit is contained in:
@@ -40,33 +40,33 @@ public class OrderJob {
|
||||
* TODO
|
||||
* 注意,因为是相隔半小时检查,因此导致订单真正超时时间是 [LITEMALL_ORDER_UNPAID, 30 + LITEMALL_ORDER_UNPAID]
|
||||
*/
|
||||
@Scheduled(fixedDelay = 30 * 60 * 1000)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void checkOrderUnpaid() {
|
||||
logger.info("系统开启任务检查订单是否已经超期自动取消订单");
|
||||
|
||||
List<LitemallOrder> orderList = orderService.queryUnpaid(SystemConfig.getOrderUnpaid());
|
||||
for (LitemallOrder order : orderList) {
|
||||
// 设置订单已取消状态
|
||||
order.setOrderStatus(OrderUtil.STATUS_AUTO_CANCEL);
|
||||
order.setEndTime(LocalDateTime.now());
|
||||
if (orderService.updateWithOptimisticLocker(order) == 0) {
|
||||
throw new RuntimeException("更新数据已失效");
|
||||
}
|
||||
|
||||
// 商品货品数量增加
|
||||
Integer orderId = order.getId();
|
||||
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
|
||||
for (LitemallOrderGoods orderGoods : orderGoodsList) {
|
||||
Integer productId = orderGoods.getProductId();
|
||||
Short number = orderGoods.getNumber();
|
||||
if (productService.addStock(productId, number) == 0) {
|
||||
throw new RuntimeException("商品货品库存增加失败");
|
||||
}
|
||||
}
|
||||
logger.info("订单 ID" + order.getId() + " 已经超期自动取消订单");
|
||||
}
|
||||
}
|
||||
// @Scheduled(fixedDelay = 30 * 60 * 1000)
|
||||
// @Transactional(rollbackFor = Exception.class)
|
||||
// public void checkOrderUnpaid() {
|
||||
// logger.info("系统开启任务检查订单是否已经超期自动取消订单");
|
||||
//
|
||||
// List<LitemallOrder> orderList = orderService.queryUnpaid(SystemConfig.getOrderUnpaid());
|
||||
// for (LitemallOrder order : orderList) {
|
||||
// // 设置订单已取消状态
|
||||
// order.setOrderStatus(OrderUtil.STATUS_AUTO_CANCEL);
|
||||
// order.setEndTime(LocalDateTime.now());
|
||||
// if (orderService.updateWithOptimisticLocker(order) == 0) {
|
||||
// throw new RuntimeException("更新数据已失效");
|
||||
// }
|
||||
//
|
||||
// // 商品货品数量增加
|
||||
// Integer orderId = order.getId();
|
||||
// List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
|
||||
// for (LitemallOrderGoods orderGoods : orderGoodsList) {
|
||||
// Integer productId = orderGoods.getProductId();
|
||||
// Short number = orderGoods.getNumber();
|
||||
// if (productService.addStock(productId, number) == 0) {
|
||||
// throw new RuntimeException("商品货品库存增加失败");
|
||||
// }
|
||||
// }
|
||||
// logger.info("订单 ID" + order.getId() + " 已经超期自动取消订单");
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 自动确认订单
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.linlinjava.litemall.db.dao.LitemallOrderMapper;
|
||||
import org.linlinjava.litemall.db.dao.OrderMapper;
|
||||
import org.linlinjava.litemall.db.domain.LitemallOrder;
|
||||
import org.linlinjava.litemall.db.domain.LitemallOrderExample;
|
||||
import org.linlinjava.litemall.db.task.OrderDelayedTaskManager;
|
||||
import org.linlinjava.litemall.db.util.OrderUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -28,6 +29,8 @@ public class LitemallOrderService {
|
||||
public int add(LitemallOrder order) {
|
||||
order.setAddTime(LocalDateTime.now());
|
||||
order.setUpdateTime(LocalDateTime.now());
|
||||
OrderDelayedTaskManager manager = OrderDelayedTaskManager.getInstance();
|
||||
manager.putQueue(order);
|
||||
return litemallOrderMapper.insertSelective(order);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.linlinjava.litemall.db.task;
|
||||
|
||||
import org.linlinjava.litemall.db.domain.LitemallOrder;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.concurrent.Delayed;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class OrderDelayedTask implements Delayed {
|
||||
|
||||
|
||||
private LitemallOrder order;
|
||||
/**
|
||||
* 延时时间 单位 timeunit.milliseconds
|
||||
**/
|
||||
private long timeout;
|
||||
private long exprire;
|
||||
|
||||
public OrderDelayedTask(LitemallOrder order, long timeout) {
|
||||
this.order = order;
|
||||
this.timeout = timeout;
|
||||
this.exprire = order.getAddTime().toInstant(ZoneOffset.of("+8")).toEpochMilli() + timeout;
|
||||
}
|
||||
|
||||
public LitemallOrder getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDelay(TimeUnit unit) {
|
||||
return unit.convert(exprire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Delayed o) {
|
||||
OrderDelayedTask other = (OrderDelayedTask) o;
|
||||
long diff = order.getAddTime().toInstant(ZoneOffset.of("+8")).toEpochMilli()
|
||||
- other.getOrder().getAddTime().toInstant(ZoneOffset.of("+8")).toEpochMilli();
|
||||
if (diff > 0) {
|
||||
return 1;
|
||||
} else if (diff < 0) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OrderDelayedTask{" +
|
||||
"order=" + order +
|
||||
", timeout=" + timeout +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package org.linlinjava.litemall.db.task;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.linlinjava.litemall.db.domain.LitemallOrder;
|
||||
import org.linlinjava.litemall.db.domain.LitemallOrderGoods;
|
||||
import org.linlinjava.litemall.db.service.LitemallGoodsProductService;
|
||||
import org.linlinjava.litemall.db.service.LitemallOrderGoodsService;
|
||||
import org.linlinjava.litemall.db.service.LitemallOrderService;
|
||||
import org.linlinjava.litemall.db.util.OrderUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.DelayQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
public class OrderDelayedTaskManager {
|
||||
|
||||
private static final Log log = LogFactory.getLog(OrderDelayedTaskManager.class);
|
||||
|
||||
@Autowired
|
||||
private LitemallOrderGoodsService orderGoodsService;
|
||||
@Autowired
|
||||
private LitemallOrderService orderService;
|
||||
@Autowired
|
||||
private LitemallGoodsProductService productService;
|
||||
|
||||
private DelayQueue<OrderDelayedTask> queue;
|
||||
|
||||
// 守护线程
|
||||
private Thread daemonThread;
|
||||
|
||||
|
||||
private static OrderDelayedTaskManager instance = new OrderDelayedTaskManager();
|
||||
|
||||
private OrderDelayedTaskManager() {
|
||||
queue = new DelayQueue<>();
|
||||
init();
|
||||
}
|
||||
|
||||
public static OrderDelayedTaskManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
public void init() {
|
||||
daemonThread = new Thread(() -> execute());
|
||||
daemonThread.setName("DelayQueueMonitor");
|
||||
daemonThread.start();
|
||||
}
|
||||
|
||||
|
||||
public void execute() {
|
||||
while (true) {
|
||||
log.info("当前延时队列的任务数量:" + queue.size());
|
||||
try {
|
||||
OrderDelayedTask task = queue.take();
|
||||
if (null != task) {
|
||||
LitemallOrder order = task.getOrder();
|
||||
if (null == order) {
|
||||
continue;
|
||||
}
|
||||
// 设置订单已取消状态
|
||||
order.setOrderStatus(OrderUtil.STATUS_AUTO_CANCEL);
|
||||
order.setEndTime(LocalDateTime.now());
|
||||
if (orderService.updateWithOptimisticLocker(order) == 0) {
|
||||
throw new RuntimeException("更新数据已失效");
|
||||
}
|
||||
// 商品货品数量增加
|
||||
Integer orderId = order.getId();
|
||||
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
|
||||
for (LitemallOrderGoods orderGoods : orderGoodsList) {
|
||||
Integer productId = orderGoods.getProductId();
|
||||
Short number = orderGoods.getNumber();
|
||||
if (productService.addStock(productId, number) == 0) {
|
||||
throw new RuntimeException("商品货品库存增加失败");
|
||||
}
|
||||
}
|
||||
log.info("订单 ID" + order.getId() + " 已经超期自动取消订单");
|
||||
log.info("end:" + LocalDateTime.now());
|
||||
}
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
log.error("获取延时任务失败!", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void putQueue(LitemallOrder order) {
|
||||
OrderDelayedTask task = new OrderDelayedTask(order, TimeUnit.MINUTES.toMillis(30));
|
||||
queue.put(task);
|
||||
}
|
||||
|
||||
public void removeQueue(OrderDelayedTask task) {
|
||||
queue.remove(task);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user