feat(OrderServiceImpl.java): SeatsAT->TCC模式改造

1、提交订单功能充AT模式可以切换到TCC模式
2、对应的冻结库存TCC模式添加
3、相关功能测试(异常回滚的执行)

Closes #I414QN
This commit is contained in:
DaniR 2021-07-17 10:54:48 +08:00
parent f6e5e6bd07
commit 4b091b20dd
4 changed files with 26 additions and 32 deletions

View File

@ -37,6 +37,7 @@ import io.seata.spring.annotation.GlobalTransactional;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
@ -67,7 +68,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
private final MemberFeignClient memberFeignClient;
private final BusinessNoGenerator businessNoGenerator;
private final SeataTccOrderService seataTccOrderService;
private SeataTccOrderService seataTccOrderService;
/**
* 订单确认
@ -220,12 +221,12 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
log.info("=======================订单提交=======================\n订单提交信息{}", submitDTO);
// 订单重复提交校验
String orderToken = submitDTO.getOrderToken();
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(RELEASE_LOCK_LUA_SCRIPT, Long.class);
Long result = this.redisTemplate.execute(redisScript, Collections.singletonList(ORDER_TOKEN_PREFIX + orderToken), orderToken);
if (!ObjectUtil.equals(result, RELEASE_LOCK_SUCCESS_RESULT)) {
throw new BizException("订单不可重复提交");
}
// DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(RELEASE_LOCK_LUA_SCRIPT, Long.class);
// Long result = this.redisTemplate.execute(redisScript, Collections.singletonList(ORDER_TOKEN_PREFIX + orderToken), orderToken);
//
// if (!ObjectUtil.equals(result, RELEASE_LOCK_SUCCESS_RESULT)) {
// throw new BizException("订单不可重复提交");
// }
List<OrderItemDTO> orderItems = submitDTO.getOrderItems();
if (CollectionUtil.isEmpty(orderItems)) {

View File

@ -6,18 +6,18 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.youlai.common.web.util.JwtUtils;
import com.youlai.mall.oms.enums.OrderStatusEnum;
import com.youlai.mall.oms.enums.OrderTypeEnum;
import com.youlai.mall.oms.mapper.OrderMapper;
import com.youlai.mall.oms.pojo.dto.OrderItemDTO;
import com.youlai.mall.oms.pojo.dto.OrderSubmitDTO;
import com.youlai.mall.oms.pojo.entity.OmsOrder;
import com.youlai.mall.oms.pojo.entity.OmsOrderItem;
import com.youlai.mall.oms.service.IOrderItemService;
import com.youlai.mall.oms.service.IOrderService;
import com.youlai.mall.oms.tcc.idempotent.IdempotentUtil;
import com.youlai.mall.oms.tcc.service.SeataTccOrderService;
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.LocalTCC;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
@ -26,10 +26,11 @@ import java.util.Objects;
import java.util.stream.Collectors;
@Slf4j
@LocalTCC
@Component
public class SeataTccOrderServiceImpl implements SeataTccOrderService {
@Autowired
private IOrderService orderService;
private OrderMapper orderMapper;
@Autowired
private IOrderItemService orderItemService;
@ -50,7 +51,8 @@ public class SeataTccOrderServiceImpl implements SeataTccOrderService {
.setTotalQuantity(orderItems.stream().map(item -> item.getCount()).reduce(0, (x, y) -> x + y))
.setTotalAmount(orderItems.stream().map(item -> item.getPrice() * item.getCount()).reduce(0l, (x, y) -> x + y))
.setGmtCreate(new Date());
orderService.save(order);
orderMapper.insert(order);
int i = 1 / 0;
// 创建订单商品
List<OmsOrderItem> orderItemList = orderItems.stream().map(item -> OmsOrderItem.builder()
.orderId(order.getId())
@ -72,9 +74,8 @@ public class SeataTccOrderServiceImpl implements SeataTccOrderService {
@Override
@Transactional
public boolean commitSubmitOrder(BusinessActionContext businessActionContext) {
log.info("==========已经完成Confirm-->创建 订单 第二阶段提交,事务组Xid:{} ==========", businessActionContext.getXid());
if (Objects.isNull(IdempotentUtil.getMarker(getClass(), businessActionContext.getXid()))) {
log.info("已执行过Confirm阶段");
return true;
}
IdempotentUtil.removeMarker(getClass(), businessActionContext.getXid());
@ -84,21 +85,18 @@ public class SeataTccOrderServiceImpl implements SeataTccOrderService {
@Override
@Transactional
public boolean rollbackSubmitOrder(BusinessActionContext businessActionContext) {
log.info("======================rollbackSubmitOrder========================");
if (Objects.isNull(IdempotentUtil.getMarker(getClass(), businessActionContext.getXid()))) {
log.info("已执行过rollback阶段");
return true;
}
JSONObject jsonObject = (JSONObject) businessActionContext.getActionContext("orderSubmitDTO");
OrderSubmitDTO orderSubmitDTO = new OrderSubmitDTO();
BeanUtil.copyProperties(jsonObject, orderSubmitDTO);
OmsOrder omsOrder = orderService.getOne(new LambdaQueryWrapper<OmsOrder>().eq(OmsOrder::getOrderSn, orderSubmitDTO.getOrderToken()));
OmsOrder omsOrder = orderMapper.selectOne(new LambdaQueryWrapper<OmsOrder>().eq(OmsOrder::getOrderSn, orderSubmitDTO.getOrderToken()));
if (Objects.nonNull(omsOrder)) {
orderItemService.remove(new LambdaQueryWrapper<OmsOrderItem>().eq(OmsOrderItem::getOrderId, omsOrder.getId()));
orderService.deleteOrder(omsOrder.getId());
orderMapper.deleteById(omsOrder.getId());
}
IdempotentUtil.removeMarker(getClass(), businessActionContext.getXid());
log.info("========== 已经完成Cancle-->第二阶段回滚,事务组Xid:{} ==========" + businessActionContext.getXid());
return true;
}
}

View File

@ -19,6 +19,7 @@ import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
@ -30,17 +31,17 @@ import static com.youlai.mall.pms.common.constant.PmsConstants.LOCK_SKU_PREFIX;
@Service
@Slf4j
@AllArgsConstructor
public class PmsSkuServiceImpl extends ServiceImpl<PmsSkuMapper, PmsSku> implements IPmsSkuService {
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private RedissonClient redissonClient;
@Autowired
private SeataTccSkuService seataTccSkuService;
@GlobalTransactional
@Override
@GlobalTransactional
public boolean lockStockTcc(List<SkuLockDTO> skuLockList) {
seataTccSkuService.prepareSkuLockList(null,skuLockList);

View File

@ -34,16 +34,13 @@ public class SeataTccSkuServiceImpl implements SeataTccSkuService {
@Autowired
private RedissonClient redissonClient;
@Transactional
@Override
@Transactional
public boolean prepareSkuLockList(BusinessActionContext businessActionContext, List<SkuLockDTO> skuLockList) {
log.info("=======================创建订单,开始锁定商品库存=======================");
//防幂等
if (Objects.nonNull(IdempotentUtil.getMarker(getClass(), businessActionContext.getXid()))) {
log.info("已执行过try阶段");
return true;
}
log.info("锁定商品信息:{}", skuLockList.toString());
if (CollectionUtil.isEmpty(skuLockList)) {
throw new BizException("锁定的商品列表为空");
}
@ -80,9 +77,7 @@ public class SeataTccSkuServiceImpl implements SeataTccSkuService {
@Transactional
@Override
public boolean commitSkuLockList(BusinessActionContext businessActionContext) {
log.info("=====================commitSkuLockList 成功=========================");
if (Objects.isNull(IdempotentUtil.getMarker(getClass(), businessActionContext.getXid()))) {
log.info(businessActionContext.getXid() + ": 已执行过commit阶段");
return true;
}
IdempotentUtil.removeMarker(getClass(), businessActionContext.getXid());
@ -92,9 +87,8 @@ public class SeataTccSkuServiceImpl implements SeataTccSkuService {
@Transactional
@Override
public boolean rollbackSkuLockList(BusinessActionContext businessActionContext) {
log.info("======================rollbackSkuLockList========================");
if (Objects.isNull(IdempotentUtil.getMarker(getClass(), businessActionContext.getXid()))) {
log.info(businessActionContext.getXid() + ": 已执行过rollback阶段");
return true;
}
JSONArray jsonObjectList = (JSONArray) businessActionContext.getActionContext("skuLockList");