Description or Example
# 知识点
## 发送手动释放库存的消息的要点
> 我这里采取的是将发送手动释放库存的消息放到ACK外, 因为, 发送这个消息是否成功并不能作为是否能成功处理当前消息的依据, 即, 即使消息发送失败了, 可以用日志重新发送, 没有必要重新入队
# 核心代码
```java
@Component
@RabbitListener(queues = "order-release-order-queue")
public class OrderListener {
@Autowired
private OrderFeignService orderFeignService;
@Autowired
private WareSender wareSender;
@Autowired
private SendMsgUtil sendMsgUtil;
@RabbitHandler
public void toCancelOrder(Message message, String orderSn, Channel channel) throws IOException {
try {
R info = orderFeignService.updateOrderStatus(orderSn);
if (info.getCode() != 0) {
// 更新订单失败
throw new RuntimeException("更新订单失败");
}
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); // 更新订单成功
// 更新日志, 成功处理消息
sendMsgUtil.finish(message.getMessageProperties().getMessageId());
}catch (Exception e) {
channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
}
//todo: 解决重新入队的问题
wareSender.sendMsgWithOrderToRelease(orderSn);
}
}
```
```java
@PostMapping("/unlock/all/sku/stock")
public R unLockSkusStock(@RequestBody List<WareOrderTaskDetailEntity> detailEntities) {
try {
Boolean isSuccess = wareInfoService.unLockSkusStock(detailEntities);
if (!isSuccess) return R.error("释放库存失败");
} catch (Exception e) {
R.error(e.getMessage());
}
return R.ok();
}
```
```java
@Override
@Transactional
public Boolean unLockSkusStock(List<WareOrderTaskDetailEntity> detailEntities) {
// 有库存的情况下批量解锁库存
if (detailEntities != null && !detailEntities.isEmpty()) {
// 先过滤掉所有已经解锁了的, 留下锁定的, 只有锁定的才可以解锁
detailEntities.stream()
.filter(detail -> WareConstant.LockEnum.LOCKED.getCode() == detail.getLockStatus())
.forEach(detail -> {
if (wareSkuService.releaseStock(detail)) {
// 如果释放库存成功, 更新工作单状态
detail.setLockStatus(WareConstant.LockEnum.UN_LOCKED.getCode());
wareOrderTaskDetailService.updateById(detail);
}else {
// 释放库存失败
throw new StockException("释放库存失败"); // 这样可以批量回滚
}
});
}
return true;
}
```