|
@@ -73,39 +73,69 @@ public class BidServiceImpl implements IBidService
|
|
|
@Override
|
|
@Override
|
|
|
@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
|
|
@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
|
|
|
public void addPrice(BidVO bid, Runnable runnable) throws RuntimeException {
|
|
public void addPrice(BidVO bid, Runnable runnable) throws RuntimeException {
|
|
|
- locker.tryLock(Constants.REDIS_LOCK_SYNC_LOT_TEMPLATE, () -> {
|
|
|
|
|
- locker.tryLock(String.format(Constants.REDIS_LOCK_LOT_TEMPLATE, bid.getLotId()), () ->{
|
|
|
|
|
- Live live = redisCache.getCacheMapValue(String.format(Constants.REDIS_MAP_AUC_LOT_TEMPLATE, bid.getAuctionId()), bid.getLotId().toString());
|
|
|
|
|
- Long previousEndTime = live.getCurrentEndTime();
|
|
|
|
|
- // 插入新的出价
|
|
|
|
|
- insertCurrBid(bid, live.getRound());
|
|
|
|
|
- // 执行addPrice方法之前已进行了拍卖状态的判断
|
|
|
|
|
- // 但由于是在分布式锁之外判断的 这里做二次判断 以防并发问题
|
|
|
|
|
- String currentStatus = ruleHandlerHolder.getCurrentStatus(live);
|
|
|
|
|
- if (Objects.equals(Constants.LOT_STATUS_STARTING, currentStatus) || Objects.equals(Constants.LOT_STATUS_BIDDING, currentStatus)) {
|
|
|
|
|
- Lot dbUpdate = Lot.builder().id(live.getLot().getId()).build();
|
|
|
|
|
- LiveContext liveContext = LiveContext.builder().dbLot(dbUpdate).live(live).dbBid(bid).build();
|
|
|
|
|
- ruleHandlerHolder.addPrice(liveContext); // 实时计算中。。。。
|
|
|
|
|
- if (StringUtils.isEmpty(liveContext.getError())) {
|
|
|
|
|
- // 到这一步 已经完成了实时数据的计算 以下代码就需要对这些计算结果落库或者更新缓存
|
|
|
|
|
- runnable.run(); // 实际这里执行的是扣减积分的操作
|
|
|
|
|
- lotMapper.updateLot(dbUpdate);
|
|
|
|
|
- List<Bid> bidList = bidMapper.selectBidListLimit(live.getLot().getId(), 20L);
|
|
|
|
|
- redisCache.setList(String.format(Constants.REDIS_MAP_AUC_LOT_BID_TEMPLATE, live.getLot().getId()), bidList);
|
|
|
|
|
- live.getLot().setProperties(null);
|
|
|
|
|
- redisCache.setCacheMapValue(String.format(Constants.REDIS_MAP_AUC_LOT_TEMPLATE, live.getLot().getAuctionId()), live.getLot().getId().toString(), live);
|
|
|
|
|
- publishRealtime(live, previousEndTime);
|
|
|
|
|
- // 这里发送 状态变更消息 其中同步内存中的缓存和发送IM消息给APP
|
|
|
|
|
- //TODO 异常问题
|
|
|
|
|
|
|
+ locker.tryLock(Constants.REDIS_LOCK_SYNC_LOT_TEMPLATE, () -> locker.tryLock(String.format(Constants.REDIS_LOCK_LOT_TEMPLATE, bid.getLotId()), () ->{
|
|
|
|
|
+ Live live = redisCache.getCacheMapValue(String.format(Constants.REDIS_MAP_AUC_LOT_TEMPLATE, bid.getAuctionId()), bid.getLotId().toString());
|
|
|
|
|
+ if (Objects.isNull(live)) {
|
|
|
|
|
+ live = rebuildLive(bid);
|
|
|
|
|
+ }
|
|
|
|
|
+ Long previousEndTime = live.getCurrentEndTime();
|
|
|
|
|
+ // 插入新的出价
|
|
|
|
|
+ insertCurrBid(bid, live.getRound());
|
|
|
|
|
+ // 执行addPrice方法之前已进行了拍卖状态的判断
|
|
|
|
|
+ // 但由于是在分布式锁之外判断的 这里做二次判断 以防并发问题
|
|
|
|
|
+ String currentStatus = ruleHandlerHolder.getCurrentStatus(live);
|
|
|
|
|
+ if (Objects.equals(Constants.LOT_STATUS_STARTING, currentStatus) || Objects.equals(Constants.LOT_STATUS_BIDDING, currentStatus)) {
|
|
|
|
|
+ Lot dbUpdate = Lot.builder().id(live.getLot().getId()).build();
|
|
|
|
|
+ LiveContext liveContext = LiveContext.builder().dbLot(dbUpdate).live(live).dbBid(bid).build();
|
|
|
|
|
+ ruleHandlerHolder.addPrice(liveContext); // 实时计算中。。。。
|
|
|
|
|
+ if (StringUtils.isEmpty(liveContext.getError())) {
|
|
|
|
|
+ // 到这一步 已经完成了实时数据的计算 以下代码就需要对这些计算结果落库或者更新缓存
|
|
|
|
|
+ runnable.run(); // 实际这里执行的是扣减积分的操作
|
|
|
|
|
+ lotMapper.updateLot(dbUpdate);
|
|
|
|
|
+ List<Bid> bidList = bidMapper.selectBidListLimit(live.getLot().getId(), 20L);
|
|
|
|
|
+ redisCache.setList(String.format(Constants.REDIS_MAP_AUC_LOT_BID_TEMPLATE, live.getLot().getId()), bidList);
|
|
|
|
|
+ live.getLot().setProperties(null);
|
|
|
|
|
+ redisCache.setCacheMapValue(String.format(Constants.REDIS_MAP_AUC_LOT_TEMPLATE, live.getLot().getAuctionId()), live.getLot().getId().toString(), live);
|
|
|
|
|
+ publishRealtime(live, previousEndTime);
|
|
|
|
|
+ // 这里发送 状态变更消息 其中同步内存中的缓存和发送IM消息给APP
|
|
|
|
|
+ //TODO 异常问题
|
|
|
// eventPublisher.publishChangeEvent(new ChangeEvent(live, null, bidList));
|
|
// eventPublisher.publishChangeEvent(new ChangeEvent(live, null, bidList));
|
|
|
- }else {
|
|
|
|
|
- throw new AddPriceException(liveContext.getError());
|
|
|
|
|
- }
|
|
|
|
|
}else {
|
|
}else {
|
|
|
- throw new AddPriceException("拍卖已结束");
|
|
|
|
|
|
|
+ throw new AddPriceException(liveContext.getError());
|
|
|
}
|
|
}
|
|
|
- }, true);
|
|
|
|
|
- }, true);
|
|
|
|
|
|
|
+ }else {
|
|
|
|
|
+ throw new AddPriceException("拍卖已结束");
|
|
|
|
|
+ }
|
|
|
|
|
+ }, true), true);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Live rebuildLive(BidVO bid) {
|
|
|
|
|
+ log.warn("addPrice live cache missing, rebuild from db, auctionId:{} lotId:{}",
|
|
|
|
|
+ bid.getAuctionId(), bid.getLotId());
|
|
|
|
|
+ Lot lot = lotMapper.selectLotById(bid.getLotId());
|
|
|
|
|
+ if (Objects.isNull(lot)) {
|
|
|
|
|
+ throw new AddPriceException("lot not found");
|
|
|
|
|
+ }
|
|
|
|
|
+ List<Bid> bids = bidMapper.selectBidList(Bid.builder().lotId(bid.getLotId()).build());
|
|
|
|
|
+ LiveContext liveContext = LiveContext.builder()
|
|
|
|
|
+ .dbLot(lot)
|
|
|
|
|
+ .bidList(bids)
|
|
|
|
|
+ .build();
|
|
|
|
|
+ ruleHandlerHolder.sync(liveContext);
|
|
|
|
|
+ Live live = liveContext.getLive();
|
|
|
|
|
+ if (Objects.isNull(live) || Objects.isNull(live.getCurrentEndTime())) {
|
|
|
|
|
+ throw new AddPriceException("live cache missing");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (Objects.isNull(live.getLot())) {
|
|
|
|
|
+ live.setLot(lot);
|
|
|
|
|
+ }
|
|
|
|
|
+ live.getLot().setProperties(null);
|
|
|
|
|
+ redisCache.setCacheMapValue(String.format(Constants.REDIS_MAP_AUC_LOT_TEMPLATE, live.getLot().getAuctionId()),
|
|
|
|
|
+ live.getLot().getId().toString(), live);
|
|
|
|
|
+ if (Objects.nonNull(cacheMap)) {
|
|
|
|
|
+ cacheMap.putLive(live);
|
|
|
|
|
+ }
|
|
|
|
|
+ return live;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|