123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- package com.webchat.service.lottery;
- import com.fasterxml.jackson.core.type.TypeReference;
- import com.webchat.common.constants.LotteryConstants;
- import com.webchat.common.enums.RedisKeyEnum;
- import com.webchat.common.util.JsonUtil;
- import com.webchat.domain.vo.response.lottery.LotteryActivityBaseVO;
- import com.webchat.domain.vo.response.lottery.LotteryActivityVO;
- import com.webchat.domain.vo.response.lottery.LotteryItemVO;
- import com.webchat.repository.dao.lottery.ILotteryActivityDAO;
- import com.webchat.repository.dao.lottery.ILotteryItemDAO;
- import com.webchat.repository.entity.lottery.LotteryActivityEntity;
- import com.webchat.repository.entity.lottery.LotteryItemEntity;
- import com.webchat.service.RedisService;
- import org.apache.commons.collections.CollectionUtils;
- import org.apache.commons.collections.MapUtils;
- import org.apache.commons.lang3.StringUtils;
- import org.springframework.beans.BeanUtils;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.data.redis.core.DefaultTypedTuple;
- import org.springframework.data.redis.core.ZSetOperations;
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.stereotype.Service;
- import org.springframework.util.Assert;
- import java.util.Collections;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.stream.Collectors;
- /**
- * @Author 程序员七七
- * @webSite https://www.coderutil.com
- * @Date 2022/11/16 23:40
- * @description
- */
- @Service
- public class LotteryCacheService {
- @Autowired
- private ILotteryActivityDAO lotteryActivityDAO;
- @Autowired
- private ILotteryItemDAO lotteryItemDAO;
- @Autowired
- private RedisService redisService;
- /**
- * 刷新活动缓存,在活动保存后
- *
- * @param activityId
- */
- @Async
- public LotteryActivityVO refreshLotteryActivityCacheById(String activityId) {
- LotteryActivityEntity entity = lotteryActivityDAO.findByActivityId(activityId);
- return this.refreshLotteryActivityCacheByEntity(entity);
- }
- @Async
- public LotteryActivityVO refreshLotteryActivityCacheByEntity(LotteryActivityEntity entity) {
- if (entity == null) {
- return null;
- }
- String lotteryActivityId = entity.getActivityId();
- List<LotteryItemVO> lotteryItemVOList = this.getLotteryItemVoListFromDB(lotteryActivityId);
- /**
- * 刷新奖品库存缓存
- */
- this.refreshLotteryItemStockCache(lotteryActivityId, lotteryItemVOList);
- /**
- * 刷新抽奖奖品详情缓存
- */
- this.refreshLotteryItemDetailCache(lotteryActivityId, lotteryItemVOList, null);
- /**
- * 刷新活动列表缓存
- */
- this.refreshLotteryActivityListCache();
- /**
- * 刷新历史抽奖活动缓存
- */
- this.refreshLotteryActivityHistoryCache();
- /**
- * 刷新最新一期活动id缓存
- */
- this.refreshLastLotteryActivityIdCache();
- /**
- * 刷新活动详情缓存
- */
- return refreshLotteryActivityDetailCache(entity, lotteryItemVOList);
- }
- /**
- * 查询最新一期活动id
- *
- * @return
- */
- public String getLastLotteryActivityIdFromCache() {
- String key = RedisKeyEnum.LOTTERY_ACTIVITY_LAST_ID_CACHE.getKey();
- String activityId = redisService.get(key);
- if (StringUtils.isNotBlank(activityId)) {
- return activityId;
- }
- return this.refreshLastLotteryActivityIdCache();
- }
- /**
- * 刷新最新一期活动ID缓存
- *
- * @return
- */
- private String refreshLastLotteryActivityIdCache() {
- String key = RedisKeyEnum.LOTTERY_ACTIVITY_LAST_ID_CACHE.getKey();
- String activityId = lotteryActivityDAO.findByLastLotteryActivity();
- redisService.remove(key);
- if (StringUtils.isNotBlank(activityId)) {
- redisService.set(key, activityId, RedisKeyEnum.LOTTERY_ACTIVITY_LAST_ID_CACHE.getExpireTime());
- }
- return activityId;
- }
- /**
- * 刷新历史抽奖活动缓存
- */
- private void refreshLotteryActivityHistoryCache() {
- List<LotteryActivityEntity> lotteryActivityEntities =
- lotteryActivityDAO.findAllByStatusNotOrderByCreateDateDesc(
- LotteryConstants.LotteryActivityStatus.DELETED.getStatus());
- String key = RedisKeyEnum.LOTTERY_ACTIVITY_HISTORY_CACHE.getKey();
- if (CollectionUtils.isEmpty(lotteryActivityEntities)) {
- redisService.remove(key);
- return;
- }
- Set<ZSetOperations.TypedTuple<String>> tuples = lotteryActivityEntities.stream().map(
- activity -> {
- String value = String.valueOf(activity.getActivityId());
- Double score = Double.valueOf(activity.getId());
- return new DefaultTypedTuple<>(value, score);
- }).collect(Collectors.toSet());
- redisService.zadd(key, tuples, RedisKeyEnum.LOTTERY_ACTIVITY_HISTORY_CACHE.getExpireTime());
- }
- /**
- * 查询历史活动
- * @param lastId
- * @param size
- * @return
- */
- public List<LotteryActivityBaseVO> queryHistoryActivityFromCache(Long lastId, int size) {
- String key = RedisKeyEnum.LOTTERY_ACTIVITY_HISTORY_CACHE.getKey();
- Long maxScore = lastId == null ? Long.MAX_VALUE : lastId;
- Set<String> activityIdStrSet = redisService.zreverseRangeByScore(key, maxScore, 0, size);
- if (CollectionUtils.isEmpty(activityIdStrSet)) {
- return Collections.emptyList();
- }
- return activityIdStrSet.stream().map(id -> {
- return this.getLotteryActivityDetailFromCache(id);
- }).collect(Collectors.toList());
- }
- /**
- * 刷新抽奖活动详情缓存
- *
- * @param entity
- * @param lotteryItemVOList
- * @return
- */
- private LotteryActivityVO refreshLotteryActivityDetailCache(LotteryActivityEntity entity,
- List<LotteryItemVO> lotteryItemVOList) {
- String lotteryActivityId = entity.getActivityId();
- RedisKeyEnum lotteryActivityCacheKey = RedisKeyEnum.LOTTERY_ACTIVITY_DETAIL_CACHE;
- String key = lotteryActivityCacheKey.getKey(lotteryActivityId);
- LotteryActivityVO lotteryActivityVO = this.covertLotteryActivityVO(entity);
- lotteryActivityVO.setItems(lotteryItemVOList);
- lotteryActivityVO.setStatusName(LotteryConstants.getLotteryActivityStatusName(entity.getStatus()));
- redisService.set(key, JsonUtil.toJsonString(lotteryActivityVO), lotteryActivityCacheKey.getExpireTime());
- return lotteryActivityVO;
- }
- /**
- * 刷新抽奖活动奖品库存余量缓存
- *
- * @param lotteryActivityId
- * @param lotteryItemVOList
- * @return MAP<itemId, stock>
- */
- public Map<Long, Integer> refreshLotteryItemStockCache(String lotteryActivityId,
- List<LotteryItemVO> lotteryItemVOList) {
- RedisKeyEnum lotteryActivityCacheKey = RedisKeyEnum.LOTTERY_ACTIVITY_ITEM_STOCK_CACHE;
- String key = lotteryActivityCacheKey.getKey(lotteryActivityId);
- if (CollectionUtils.isEmpty(lotteryItemVOList)) {
- redisService.remove(key);
- return Collections.emptyMap();
- }
- Map<Long, Integer> lotteryItemStockMap = new ConcurrentHashMap<>();
- lotteryItemVOList.stream().forEach(item -> {
- lotteryItemStockMap.put(item.getId(), item.getStock());
- });
- redisService.set(key, JsonUtil.toJsonString(lotteryItemStockMap), lotteryActivityCacheKey.getExpireTime());
- return lotteryItemStockMap;
- }
- /**
- * 刷新抽奖奖品详情缓存
- *
- * @param lotteryActivityId
- * @param lotteryItemVOList
- */
- public void refreshLotteryItemDetailCache(String lotteryActivityId, List<LotteryItemVO> lotteryItemVOList) {
- this.refreshLotteryItemDetailCache(lotteryActivityId, lotteryItemVOList, null);
- }
- public LotteryItemVO refreshLotteryItemDetailCache(String lotteryActivityId, List<LotteryItemVO> lotteryItemVOList,
- Long itemId) {
- RedisKeyEnum lotteryActivityItemDetailKey = RedisKeyEnum.LOTTERY_ACTIVITY_ITEM_DETAIL_CACHE;
- String key = lotteryActivityItemDetailKey.getKey(lotteryActivityId);
- if (CollectionUtils.isEmpty(lotteryItemVOList)) {
- redisService.remove(key);
- return null;
- }
- LotteryItemVO backItem = null;
- for (LotteryItemVO lotteryItem : lotteryItemVOList) {
- redisService.hset(key, lotteryItem.getId().toString(),
- JsonUtil.toJsonString(lotteryItem), lotteryActivityItemDetailKey.getExpireTime());
- if (itemId != null && itemId.equals(lotteryItem.getId())) {
- backItem = lotteryItem;
- }
- }
- return backItem;
- }
- /**
- * 查询抽奖商品信息
- *
- * @param lotteryActivityId
- * @param itemId
- * @return
- */
- public LotteryItemVO getLotteryItemVOFromCache(String lotteryActivityId, Long itemId) {
- RedisKeyEnum lotteryActivityItemDetailKey = RedisKeyEnum.LOTTERY_ACTIVITY_ITEM_DETAIL_CACHE;
- String key = lotteryActivityItemDetailKey.getKey(lotteryActivityId);
- String cache = redisService.hget(key, String.valueOf(itemId));
- if (StringUtils.isNotBlank(cache)) {
- return JsonUtil.fromJson(cache, LotteryItemVO.class);
- }
- List<LotteryItemVO> lotteryItemVOList = this.getLotteryItemVoListFromDB(lotteryActivityId);
- return refreshLotteryItemDetailCache(lotteryActivityId, lotteryItemVOList, itemId);
- }
- /**
- * 查询抽奖活动奖品库存数据
- *
- * @param lotteryActivityId
- * @return
- */
- public Map<Long, Integer> getLotteryItemStockFromCache(String lotteryActivityId) {
- RedisKeyEnum lotteryActivityCacheKey = RedisKeyEnum.LOTTERY_ACTIVITY_ITEM_STOCK_CACHE;
- String key = lotteryActivityCacheKey.getKey(lotteryActivityId);
- String stockCache = redisService.get(key);
- if (StringUtils.isNotBlank(stockCache)) {
- return JsonUtil.fromJson(stockCache, new TypeReference<ConcurrentHashMap<Long, Integer>>() {
- });
- }
- return Collections.emptyMap();
- }
- /**
- * 抽奖出结果后扣减库存
- *
- * @param lotteryActivityId
- * @param itemId
- */
- public void deductItemStock(String lotteryActivityId, Long itemId) {
- // 这里目前不是原子性操作,在高并发情况下可能会有问题
- RedisKeyEnum lotteryActivityCacheKey = RedisKeyEnum.LOTTERY_ACTIVITY_ITEM_STOCK_CACHE;
- String key = lotteryActivityCacheKey.getKey(lotteryActivityId);
- Map<Long, Integer> stockMap = this.getLotteryItemStockFromCache(lotteryActivityId);
- Assert.isTrue(MapUtils.isNotEmpty(stockMap), "库存为空");
- stockMap.put(itemId, stockMap.get(itemId) - 1);
- redisService.set(key, JsonUtil.toJsonString(stockMap), lotteryActivityCacheKey.getExpireTime());
- }
- /**
- * 查询活动下的奖品列表
- *
- * @param activityId
- * @return
- */
- private List<LotteryItemVO> getLotteryItemVoListFromDB(String activityId) {
- List<LotteryItemEntity> lotteryItemEntities = lotteryItemDAO.findAllByActivityIdOrderBySlotAsc(activityId);
- if (CollectionUtils.isEmpty(lotteryItemEntities)) {
- return Collections.emptyList();
- }
- return lotteryItemEntities.stream().map(item -> {
- LotteryItemVO lotteryItemVO = new LotteryItemVO();
- BeanUtils.copyProperties(item, lotteryItemVO);
- lotteryItemVO.setTypeName(LotteryConstants.getLotteryActivityItemTypeName(item.getType()));
- return lotteryItemVO;
- }).collect(Collectors.toList());
- }
- private LotteryActivityVO covertLotteryActivityVO(LotteryActivityEntity entity) {
- LotteryActivityVO lotteryActivityVO = new LotteryActivityVO();
- BeanUtils.copyProperties(entity, lotteryActivityVO);
- lotteryActivityVO.setCreateTime(entity.getCreateDate().getTime());
- return lotteryActivityVO;
- }
- /**
- * 查询最新一期活动
- *
- * @return
- */
- public LotteryActivityVO getLastLotteryActivityDetailFromCache() {
- String activityId = this.getLastLotteryActivityIdFromCache();
- if (StringUtils.isBlank(activityId)) {
- return null;
- }
- return this.getLotteryActivityDetailFromCache(activityId);
- }
- /**
- * 查询抽奖活动详情
- *
- * @param lotteryActivityId
- * @return
- */
- public LotteryActivityVO getLotteryActivityDetailFromCache(String lotteryActivityId) {
- RedisKeyEnum lotteryActivityCacheKey = RedisKeyEnum.LOTTERY_ACTIVITY_DETAIL_CACHE;
- String key = lotteryActivityCacheKey.getKey(lotteryActivityId);
- String lotteryActivityCache = redisService.get(key);
- LotteryActivityVO lotteryActivity;
- if (StringUtils.isNotBlank(lotteryActivityCache)) {
- lotteryActivity = JsonUtil.fromJson(lotteryActivityCache, LotteryActivityVO.class);
- } else {
- lotteryActivity = this.refreshLotteryActivityCacheById(lotteryActivityId);
- }
- return lotteryActivity;
- }
- /**
- * 刷新抽奖活动缓存
- */
- private void refreshLotteryActivityListCache() {
- }
- }
|