Commit e95948bf authored by 朱洪锦's avatar 朱洪锦
Browse files

通过延时队列实现检查订单是否已经超期,自动取消订单的功能

parent 3ad47b5b
......@@ -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);
}
......
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 +
'}';
}
}
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);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment