diff --git a/framework/src/main/java/cn/lili/common/enums/ResultCode.java b/framework/src/main/java/cn/lili/common/enums/ResultCode.java index 655e4cb9..87e9f0ae 100644 --- a/framework/src/main/java/cn/lili/common/enums/ResultCode.java +++ b/framework/src/main/java/cn/lili/common/enums/ResultCode.java @@ -449,7 +449,8 @@ public enum ResultCode { CUSTOM_WORDS_SECRET_KEY_ERROR(90002, "秘钥验证失败!"), CONNECT_NOT_EXIST(90000, "登录方式不存在!"), ELASTICSEARCH_INDEX_INIT_ERROR(90003, "索引初始化失败!"), - PURCHASE_ORDER_DEADLINE_ERROR(90004, "供求单,已超过报名截止时间"); + PURCHASE_ORDER_DEADLINE_ERROR(90004, "供求单,已超过报名截止时间"), + INDEX_BUILDING(90005, "索引正在生成"); private final Integer code; private final String message; diff --git a/framework/src/main/java/cn/lili/modules/search/service/EsGoodsIndexService.java b/framework/src/main/java/cn/lili/modules/search/service/EsGoodsIndexService.java index a33c8928..f7edeb7e 100644 --- a/framework/src/main/java/cn/lili/modules/search/service/EsGoodsIndexService.java +++ b/framework/src/main/java/cn/lili/modules/search/service/EsGoodsIndexService.java @@ -18,6 +18,16 @@ import java.util.Map; **/ public interface EsGoodsIndexService { + /** + * 全局索引初始化 + */ + void init(); + + /** + * 获取es生成索引进度 + * @return + */ + Map getProgress(); /** * 添加商品索引 * diff --git a/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java b/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java index 65b3254a..ed5a1ce9 100644 --- a/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java @@ -2,6 +2,8 @@ package cn.lili.modules.search.serviceimpl; import cn.hutool.core.date.DateUtil; import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ReflectUtil; import cn.hutool.extra.pinyin.PinyinUtil; import cn.hutool.json.JSONObject; @@ -9,14 +11,18 @@ import cn.hutool.json.JSONUtil; import cn.lili.cache.Cache; import cn.lili.cache.CachePrefix; import cn.lili.common.enums.PromotionTypeEnum; +import cn.lili.common.enums.ResultCode; +import cn.lili.common.enums.ResultUtil; +import cn.lili.common.exception.ServiceException; import cn.lili.elasticsearch.BaseElasticsearchService; import cn.lili.elasticsearch.EsSuffix; import cn.lili.elasticsearch.config.ElasticsearchProperties; -import cn.lili.modules.goods.entity.dos.GoodsSku; -import cn.lili.modules.goods.entity.dos.GoodsWords; +import cn.lili.modules.goods.entity.dos.*; import cn.lili.modules.goods.entity.dto.GoodsParamsDTO; +import cn.lili.modules.goods.entity.enums.GoodsAuthEnum; +import cn.lili.modules.goods.entity.enums.GoodsStatusEnum; import cn.lili.modules.goods.entity.enums.GoodsWordsTypeEnum; -import cn.lili.modules.goods.service.GoodsWordsService; +import cn.lili.modules.goods.service.*; import cn.lili.modules.promotion.entity.dos.PromotionGoods; import cn.lili.modules.promotion.entity.dto.BasePromotion; import cn.lili.modules.promotion.entity.enums.PromotionStatusEnum; @@ -27,6 +33,8 @@ import cn.lili.modules.search.entity.dto.EsGoodsSearchDTO; import cn.lili.modules.search.repository.EsGoodsIndexRepository; import cn.lili.modules.search.service.EsGoodsIndexService; import cn.lili.modules.search.service.EsGoodsSearchService; +import cn.lili.modules.store.entity.dos.StoreGoodsLabel; +import cn.lili.modules.store.service.StoreGoodsLabelService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.extern.slf4j.Slf4j; import org.assertj.core.util.IterableUtil; @@ -78,9 +86,111 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements private GoodsWordsService goodsWordsService; @Autowired private PromotionService promotionService; + + + @Autowired + private GoodsSkuService goodsSkuService; + @Autowired + private GoodsService goodsService; + @Autowired + private BrandService brandService; + + @Autowired + private CategoryService categoryService; + + @Autowired + private StoreGoodsLabelService storeGoodsLabelService; @Autowired private Cache cache; + @Override + public void init() { + //获取索引任务标识 + Boolean flag = (Boolean) cache.get(CachePrefix.INIT_INDEX_FLAG.getPrefix()); + //为空则默认写入没有任务 + if (flag == null) { + cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), false); + } + //有正在初始化的任务,则提示异常 + if (Boolean.TRUE.equals(flag)) { + throw new ServiceException(ResultCode.INDEX_BUILDING); + } + + //初始化标识 + cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), null); + cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), true); + + ThreadUtil.execAsync(() -> { + try { + //查询商品信息 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(GoodsSku::getIsAuth, GoodsAuthEnum.PASS.name()); + queryWrapper.eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name()); + + List list = goodsSkuService.list(queryWrapper); + List esGoodsIndices = new ArrayList<>(); + //库存锁是在redis做的,所以生成索引,同时更新一下redis中的库存数量 + for (GoodsSku goodsSku : list) { + Goods goods = goodsService.getById(goodsSku.getGoodsId()); + //如果出现极端情况,有sku,没有与之匹配的商品,则跳过 + if (goods == null) { + continue; + } + EsGoodsIndex index = new EsGoodsIndex(goodsSku); + + //商品参数索引 + if (goods.getParams() != null && !goods.getParams().isEmpty()) { + List goodsParamDTOS = JSONUtil.toList(goods.getParams(), GoodsParamsDTO.class); + index = new EsGoodsIndex(goodsSku, goodsParamDTOS); + } + //商品分类索引 + if (goods.getCategoryPath() != null) { + List categories = categoryService.listByIdsOrderByLevel(Arrays.asList(goods.getCategoryPath().split(","))); + if (!categories.isEmpty()) { + index.setCategoryNamePath(ArrayUtil.join(categories.stream().map(Category::getName).toArray(), ",")); + } + } + //商品品牌索引 + Brand brand = brandService.getById(goods.getBrandId()); + if (brand != null) { + index.setBrandName(brand.getName()); + index.setBrandUrl(brand.getLogo()); + } + //店铺分类索引 + if (goods.getStoreCategoryPath() != null && CharSequenceUtil.isNotEmpty(goods.getStoreCategoryPath())) { + List storeGoodsLabels = storeGoodsLabelService.listByStoreIds(Arrays.asList(goods.getStoreCategoryPath().split(","))); + if (!storeGoodsLabels.isEmpty()) { + index.setStoreCategoryNamePath(ArrayUtil.join(storeGoodsLabels.stream().map(StoreGoodsLabel::getLabelName).toArray(), ",")); + } + } + //促销索引 + Map goodsCurrentPromotionMap = promotionService.getGoodsCurrentPromotionMap(index); + index.setPromotionMap(goodsCurrentPromotionMap); + esGoodsIndices.add(index); + cache.put(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity().toString()); + } + //初始化商品索引 + this.initIndex(esGoodsIndices); + } catch (Exception e) { + log.error("商品索引生成异常:", e); + //如果出现异常,则将进行中的任务标识取消掉,打印日志 + cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), null); + cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), false); + } + }); + } + + @Override + public Map getProgress() { + Map map = (Map) cache.get(CachePrefix.INIT_INDEX_PROCESS.getPrefix()); + if (map == null) { + return null; + } + Boolean flag = (Boolean) cache.get(CachePrefix.INIT_INDEX_FLAG.getPrefix()); + map.put("flag", Boolean.TRUE.equals(flag) ? 1 : 0); + return map; + } + @Override public void addIndex(EsGoodsIndex goods) { try { diff --git a/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java b/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java index 4770c933..45d45638 100644 --- a/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java +++ b/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java @@ -6,6 +6,7 @@ import cn.hutool.core.util.ArrayUtil; import cn.hutool.json.JSONUtil; import cn.lili.cache.Cache; import cn.lili.cache.CachePrefix; +import cn.lili.common.enums.ResultCode; import cn.lili.common.enums.ResultUtil; import cn.lili.common.vo.ResultMessage; import cn.lili.modules.goods.entity.dos.Brand; @@ -52,101 +53,17 @@ public class ElasticsearchController { @Autowired private EsGoodsIndexService esGoodsIndexService; - @Autowired - private GoodsSkuService goodsSkuService; - - @Autowired - private GoodsService goodsService; - - @Autowired - private StringRedisTemplate stringRedisTemplate; - - @Autowired - private PromotionService promotionService; - - @Autowired - private CategoryService categoryService; - - @Autowired - private BrandService brandService; - - @Autowired - private StoreGoodsLabelService storeGoodsLabelService; - @Autowired private Cache cache; @GetMapping public ResultMessage init() { - - Boolean flag = (Boolean) cache.get(CachePrefix.INIT_INDEX_FLAG.getPrefix()); - if (flag == null) { - cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), false); - } - if (Boolean.TRUE.equals(flag)) { - return ResultUtil.error(100000, "当前有任务在执行"); - } - - cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), null); - cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), true); - ThreadUtil.execAsync(() -> { - try { - //查询商品信息 - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(GoodsSku::getIsAuth, GoodsAuthEnum.PASS.name()); - queryWrapper.eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name()); - - List list = goodsSkuService.list(queryWrapper); - List esGoodsIndices = new ArrayList<>(); - //库存锁是在redis做的,所以生成索引,同时更新一下redis中的库存数量 - for (GoodsSku goodsSku : list) { - Goods goods = goodsService.getById(goodsSku.getGoodsId()); - EsGoodsIndex index = new EsGoodsIndex(goodsSku); - if (goods.getParams() != null && !goods.getParams().isEmpty()) { - List goodsParamDTOS = JSONUtil.toList(goods.getParams(), GoodsParamsDTO.class); - index = new EsGoodsIndex(goodsSku, goodsParamDTOS); - } - if (goods.getCategoryPath() != null) { - List categories = categoryService.listByIdsOrderByLevel(Arrays.asList(goods.getCategoryPath().split(","))); - if (!categories.isEmpty()) { - index.setCategoryNamePath(ArrayUtil.join(categories.stream().map(Category::getName).toArray(), ",")); - } - } - Brand brand = brandService.getById(goods.getBrandId()); - if (brand != null) { - index.setBrandName(brand.getName()); - index.setBrandUrl(brand.getLogo()); - } - if (goods.getStoreCategoryPath() != null && CharSequenceUtil.isNotEmpty(goods.getStoreCategoryPath())) { - List storeGoodsLabels = storeGoodsLabelService.listByStoreIds(Arrays.asList(goods.getStoreCategoryPath().split(","))); - if (!storeGoodsLabels.isEmpty()) { - index.setStoreCategoryNamePath(ArrayUtil.join(storeGoodsLabels.stream().map(StoreGoodsLabel::getLabelName).toArray(), ",")); - } - } - Map goodsCurrentPromotionMap = promotionService.getGoodsCurrentPromotionMap(index); - index.setPromotionMap(goodsCurrentPromotionMap); - esGoodsIndices.add(index); - stringRedisTemplate.opsForValue().set(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity().toString()); - } - //初始化商品索引 - esGoodsIndexService.initIndex(esGoodsIndices); - } catch (Exception e) { - cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), null); - cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), false); - } - }); + esGoodsIndexService.init(); return ResultUtil.success(); } @GetMapping("/progress") public ResultMessage> getProgress() { - try { - Map map = (Map) cache.get(CachePrefix.INIT_INDEX_PROCESS.getPrefix()); - Boolean flag = (Boolean) cache.get(CachePrefix.INIT_INDEX_FLAG.getPrefix()); - map.put("flag", Boolean.TRUE.equals(flag) ? 1 : 0); - return ResultUtil.data(map); - } catch (Exception e) { - return ResultUtil.data(null); - } + return ResultUtil.data(esGoodsIndexService.getProgress()); } }